一.概念
观察者模式(Observer)又称为发布-订阅模式(Publish/Subscribe),是一种一对多的依赖关系,让多个观察者对象同时监听同一个主题对象,当这个主题对象在状态发生改变时,通知所有的观察者对象,使它们能自动更新自己.
二.示例类图:
三:示例代码(C#):
using System; using System.Collections.Generic; using System.Text; namespace DesignPatternsCore { /// <summary> /// 被观察者 /// </summary> public class Subject { /// <summary> /// 需要一个容器存储所有观察者或观察方法 /// 在C#中可以使用委托,也可以使用List或者Dictionary存储被观察对象(存储的对象有相同的父类或继承接口) /// 如果使用委托存储,通知时调用委托中的所有函数即可 /// 如果使用List或Dictionary,通知时遍历并依次调用其中的指定方法 /// </summary> public Action ObserverActions; public void AddListener(Action action) { if(ObserverActions == null) { ObserverActions = action; } else { ObserverActions += action; } } public void RemoveListener(Action action) { if(ObserverActions != null) { ObserverActions -= action; } } public void Notify() { if(ObserverActions != null) { ObserverActions(); } } } /// <summary> /// 观察者A /// </summary> public class ObserverA { public ObserverA(Subject subject) { subject.AddListener(OnObserverANotified); } public void OnObserverANotified() { Console.WriteLine("observer a be notified"); } } /// <summary> /// 观察者B /// </summary> public class ObserverB { public ObserverB(Subject subject) { subject.AddListener(OnObserverBNotified); } public void OnObserverBNotified() { Console.WriteLine("observer b be notified"); } } }
四.总结
在观察者模式中,被观察者必须保存所有观察者的引用.可以使用List或键值对保存所有观察者对象引用,这要求观察者都必须有同一父类或继承自同一接口,在C#中也可以使用委托只保存观察者被激活时调用的方法.当被观察者需要通知所有观察者时,依次遍历List或键值对中保存的对象引用并调用其中的特定方法或者直接调用委托.一般在实际使用过程中使用键值对保存,这样可以使用字符串作为键存储不同种类的观察者(值为List或委托),通过键决定唤醒哪些观察者.在Unity中的事件广播就是典型的观察者模式.