行为设计模式是一类用于描述对象之间通信与职责分配的设计模式,关注“对象之间的交互”和“职责的分配”
2026/7/28 4:41:02 网站建设 项目流程

行为设计模式是一类用于描述对象之间通信与职责分配的设计模式,关注“对象之间的交互”和“职责的分配”。你提到的四种模式——观察者(Observer)、策略(Strategy)、命令(Command)和职责链(Chain of Responsibility)——均属于经典GoF 23种设计模式中的行为型模式,各自解决不同场景下的行为解耦与动态变化问题:

  • 观察者模式:定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象自动得到通知并更新(如事件监听、MVC中的View-Model联动)。
  • 策略模式:封装一系列算法,使它们可以互相替换,让算法的变化独立于使用它的客户端(如支付方式选择:微信支付、支付宝、银行卡等策略可动态切换)。
  • 命令模式:将请求封装为对象,从而可用不同的请求对客户进行参数化、支持撤销/重做、日志记录和队列操作(如GUI按钮点击、宏命令、任务调度系统)。
  • 职责链模式:使多个对象都有机会处理请求,避免请求发送者与接收者耦合,将这些对象连成一条链,并沿链传递请求,直到被处理(如审批流程:组长→部门经理→HR→CEO逐级处理)。

这四者共性在于:降低对象间的紧耦合,提升行为的可扩展性与可维护性;差异在于关注点不同——观察者聚焦“状态变更通知”,策略聚焦“算法替换”,命令聚焦“请求封装与控制”,职责链聚焦“请求分发与响应权移交”。

# 示例:简易策略模式实现(支付策略)fromabcimportABC,abstractmethodclassPaymentStrategy(ABC):@abstractmethoddefpay(self,amount:float)->str:passclassWeChatPay(PaymentStrategy):defpay(self,amount:float)->str:returnf"微信支付{amount}元"classAlipay(PaymentStrategy):defpay(self,amount:float)->str:returnf"支付宝支付{amount}元"classPaymentContext:def__init__(self,strategy:PaymentStrategy):self._strategy=strategydefexecute_payment(self,amount:float)->str:returnself._strategy.pay(amount)# 使用ctx=PaymentContext(WeChatPay())print(ctx.execute_payment(99.9))# 微信支付 99.9 元

在观察者模式中,内存泄漏常源于循环引用(circular reference):被观察者(Subject)持有了观察者(Observer)的强引用,而观察者又可能通过回调、闭包或内部类等方式持有被观察者的引用,导致垃圾回收器无法释放对象(尤其在长期运行系统如GUI应用、服务端事件总线中尤为关键)。


✅ Java 中的典型解决方案:

  1. 使用弱引用(WeakReference)管理观察者
    将观察者存入WeakReference<Observer>列表,使GC可在无其他强引用时回收观察者,避免被观察者阻止其销毁:

    publicclassSubject{privatefinalList<WeakReference<Observer>>observers=newArrayList<>();publicvoidaddObserver(Observerobs){observers.add(newWeakReference<>(obs));}publicvoidnotifyObservers(){// 过滤已回收的观察者observers.removeIf(ref->ref.get()==null);observers.forEach(ref->{Observerobs=ref.get();if(obs!=null)obs.update(this);});}}
  2. 显式解注册(Unregister)+try-finally/AutoCloseable
    要求观察者在生命周期结束前调用removeObserver(),配合try-with-resourcesDisposable接口(如RxJava的Disposable)确保清理。

  3. 使用java.util.concurrent.CopyOnWriteArrayList+ 显式管理
    线程安全,但需配合手动移除逻辑;适用于观察者数量少、变更不频繁场景。

  4. 框架级方案

    • Android 中LiveData内部使用LifecycleOwner绑定生命周期,自动解注册;
    • Spring 的ApplicationEventPublisher配合@EventListenerSmartLifecycle实现自动销毁感知。

✅ Python 中的典型解决方案:

  1. 使用weakref.WeakKeyDictionaryweakref.WeakSet
    WeakKeyDictionary以观察者为 key,自动在观察者被回收时剔除条目(要求观察者是可哈希的);WeakSet更通用(支持任意对象):

    importweakrefclassSubject:def__init__(self):self._observers=weakref.WeakSet()# 自动清理已销毁的observerdefattach(self,observer):self._observers.add(observer)defnotify(self,data):# WeakSet 迭代时自动跳过已回收对象forobsinlist(self._observers):# list() 防止迭代中修改obs.update(data)
  2. 避免闭包捕获self引用(尤其在 lambda 或嵌套函数中)
    ❌ 危险示例:

    defregister(self,obj):self.observers.append(lambda:self.handle(obj))# 捕获 self → 循环引用!

    ✅ 安全替代:用functools.partial或显式传参,或改用绑定方法(obj.method是 bound method,但需确保obj不反向引用self)。

  3. 上下文管理器(with语句)或__del__辅助清理(慎用)
    更推荐显式unregister()+ 上下文协议(如contextlib.closing),因__del__执行时机不确定且不可靠。

  4. 现代方案:asyncio事件总线 +weakref.ref回调
    在异步系统中,结合asyncio.create_task()和弱引用回调,避免任务长期持有对象引用。


共性最佳实践

  • 观察者应无状态或弱依赖被观察者
  • 被观察者不持有观察者的业务逻辑引用,仅保留通知能力;
  • 在 GUI/Android/前端框架中,严格绑定生命周期(如onDestroy()useEffect cleanup);
  • 使用静态分析工具(Java:LeakCanary;Python:objgraphtracemalloc)检测潜在泄漏。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询