7 种行为型设计模式的核心特征与关键词总结,非常精炼准确。以下是简要归纳与补充说明,便于理解与记忆:
- 观察者模式(Observer):定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都得到通知并自动更新。适用于事件驱动系统、MVC 中的 View 与 Model 同步等场景。
- 策略模式(Strategy):将算法封装成独立类(策略类),使它们可互相替换;客户端通过组合方式使用不同策略,避免大量条件分支。典型应用:支付方式(微信/支付宝/银联)、排序算法切换。
- 状态模式(State):允许对象在其内部状态改变时改变其行为,仿佛改变了类。将状态相关的行为局部化到各自的状态类中,消除庞大的条件判断。如订单状态(待支付→已支付→发货中→已完成)。
- 模板方法模式(Template Method):定义一个操作中算法的骨架(即模板方法),而将一些步骤延迟到子类中实现。子类可不改变算法结构即可重定义该算法的某些特定步骤。“钩子(Hook)”方法用于提供扩展点。
- 命令模式(Command):将请求封装为对象,从而支持参数化、队列、日志、撤销/重做等功能。命令对象包含执行逻辑(
execute())和反向逻辑(undo()),解耦请求发起者与接收者。 - 迭代器模式(Iterator):提供一种方法顺序访问聚合对象(如列表、树、图)中的各个元素,而不暴露其底层表示。支持多种遍历方式(正向/反向/深度优先等),提升容器与遍历逻辑的解耦。
- 职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,将这些对象连成一条链,并沿着该链传递请求,直到有对象处理它为止。常用于审批流、异常处理、日志级别分发等。
# 示例:职责链模式简化版(Python)fromabcimportABC,abstractmethodclassHandler(ABC):def__init__(self,next_handler=None):self._next=next_handlerdefhandle(self,request):ifself._can_handle(request):returnself._process(request)elifself._next:returnself._next.handle(request)else:return"No handler found"@abstractmethoddef_can_handle(self,request):pass@abstractmethoddef_process(self,request):passclassLevel1Handler(Handler):def_can_handle(self,request):returnrequest<10def_process(self,request):returnf"Level1 handled{request}"classLevel2Handler(Handler):def_can_handle(self,request):returnrequest<50def_process(self,request):returnf"Level2 handled{request}"在观察者模式中,内存泄漏风险主要源于“循环引用”或“观察者未被及时解注册”,导致被观察者(Subject)长期持有对观察者(Observer)的强引用,阻止垃圾回收器释放观察者对象。以下是各主流语言的典型规避策略:
✅Java 中的解决方案:
使用
WeakReference<Observer>存储观察者:publicclassSubject{privatefinalList<WeakReference<Observer>>observers=newArrayList<>();publicvoidaddObserver(Observerobs){observers.add(newWeakReference<>(obs));}publicvoidnotifyObservers(){// 过滤已回收的观察者(避免 NullPointerException)observers.removeIf(ref->ref.get()==null);for(WeakReference<Observer>ref:observers){Observerobs=ref.get();if(obs!=null)obs.update(this);}}}✅ 优点:自动解耦生命周期;❌ 注意:需定期清理
null引用,否则WeakReference列表本身会持续增长(弱引用不自动移除)。使用
java.util.WeakHashMap<Observer, Boolean>(Key 为 Observer,值任意):利用其 Key 的弱引用特性,GC 时自动剔除条目,更简洁安全。
✅C++ 中的解决方案:
- 使用
std::weak_ptr<Observer>配合std::shared_ptr:
✅classSubject{std::vector<std::weak_ptr<Observer>>observers;public:voidaddObserver(std::shared_ptr<Observer>obs){observers.push_back(obs);}voidnotify(){observers.erase(std::remove_if(observers.begin(),observers.end(),[](constauto&w){returnw.lock()==nullptr;}),observers.end());for(auto&w:observers){if(autoobs=w.lock())obs->update(*this);}}};weak_ptr不影响引用计数,避免循环引用(如 Observer 持有 Subject 的shared_ptr);❌ 需显式调用lock()转为shared_ptr并检查有效性。
✅通用最佳实践(跨语言):
- 强制解注册机制:提供
removeObserver(),并在 Observer 生命周期结束时(如 Activity onDestroy、析构函数、__del__)主动调用; - 自动解注册(推荐):结合语言特性实现“作用域绑定”,例如:
- Java:使用
AutoCloseable+ try-with-resources 或 Lifecycle-aware 组件(AndroidLifecycleObserver); - Python:使用上下文管理器(
with subject.observe(observer): ...)或__del__+ 弱引用字典;
- Java:使用
- 避免反向强引用:Observer 不应直接持有 Subject 的强引用(可改用回调函数、事件总线或依赖注入)。
⚠️ 补充提醒:
- 在多线程环境下,
WeakReference/weak_ptr的检查与调用需加锁或使用原子操作,防止竞态(如 A 判断非空,B 此刻 GC 回收,A 执行时崩溃); - Web 前端(JavaScript)中,可用
FinalizationRegistry(实验性)或事件监听器配once: true+ 显式removeEventListener。