观察者模式(Observer) 发布-订阅模式(Publish/Subscribe) 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当这个主题对象状态发生改变时,会通知所有的观察者对象,使他们能够自动更新自己。所以也称之为发布-订阅模式(Publish/Subscribe)。
观察者模式结构图
观察者模式成员分析 Subject类,主题类,通常用一个抽象类或者抽象接口实现。他把所有对观察者对象的引用保存在一个聚集内。
observer类,观察者类,为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。 ConcreteSubject,具体主题类,存入有关状态到具体观察者对象,在具体主题内部状态发生改变时,给所有登记的观察者发出通知.
ConcreteObserver,具体观察者,在得到主题的通知时更新自己。
观察者模式代码结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 abstract class Subject { private Ilist<Observer> observers = new List<Observer>(); public void Attach(Observer observer) { observer.Add(observer); } public void Detach(Observer observer) { observer.Remove(); } public void Notify ( ) { foreach (Observer o in observers) { o.Update(); } } }abstract class observer () { public abstract void Update () ; }class ConCreteSubject : Subject { private string subjectState; public string SubjectState { get {return subjectState;} set {subjectState = value ;} } }class ConcreteObserver :Observer { private string name; private striing observerState; private ConcreteSubject subject; public ConcreteObserver (ConserverSubject subject,string name ) { this .name = name; this .subject = subject; } public override void Update () { observerState = subject.SubjectState; } public ConcreteSubject Subject { get {return subjectState;} set {subjectState = value ;} } } 客户端代码 ConcreteSubject s = new ConcreteSubject(); s.Attach(new ConcreteObserver(s,"X" )); s.Attach(new ConcreteObserver(s,"Y" )); s.SubjectState = "newState" ; s.Notify( );
观察者模式总结 观察者模式的核心思想是利用依赖倒置原则来解耦,通过抽象出主题类和观察者类两个类的抽象接口,来实现主题类一通知,观察者就随之改变状态。
用在哪里? 当将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是要维护相关对象的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、拓展和重用都带来不便。
关键对象——Subject和Observer
Subject对象不必知道具体哪个Observer,一旦发生改变,Subject将通知所有Observer。 Observer不必知道他自身具体的通知者,也不需要知道其他Observer的存在。
这样使得程序不再紧密耦合。
什么时候使用? 一般用于一个对象改变需要同时改变其他对象时,而且它不知道具体由多少个对象有待改变时,应该考虑使用观察者模式。
不足: 一个是,抽象的通知者还是依赖于抽象的观察者,如果没有这个抽象观察者接口,这个通知的接口功能就不能完成。
另一个是,对于每一个具体的观察者,不一定都是同样的“Update”方法的调用。
如果通知者和观察者之间根本就互相不知道,由客户端来决定通知谁,该如何实现?
C#观察者模式的委托实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 委托实现: 首先——两个观察者类Observer将Update更名为具体的方法Method1、Method2 第二——抽象通知者不希望依赖于抽象观察者,所有关于“增减”观察者的方法不被需要,删去。interface Subject { void Notify () ; string SubjectState{get ;set ;} } 第三——为具体通知者声明委托delegate void EventHandler () ;class Notifier1 : Subject {public event EventHandler Update;private string action;public void Notify () { Update( ); }public string SubjectState {get {return action;}set {action = value ;} } }class Notifier2 : Subject { } 客户端: Notifier1 ner = new Notifier1( ); ConcreteObserver1 zxf = new ConcreteObserver1("zxf" ,ner); ConcreteObserver1 hyx = new ConcreteObserver1("hyx" ,ner); ner.Update +=new EventHandler(zxf.Method1); ner.Update +=new EventHandler(hyx.Method2); ner.SubjectState = "xxx" ; ner.Notify( );
映射到游戏开发里面就是事件、广播等的实现