观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者同时监听某一个主题对象。这个主题对象在状态发生变化时会通知所有观察者对象,使它们自己能够自动更新自己。
介绍
使用场景:
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少个对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象...,可以使用观察者模式创建一种链式触发机制。
如何使用:一个对象的状态发生改变,所有的依赖对象都将得到通知,进行广播通知。
关键代码:在抽象类中有一个ArrayList存放观察者们。
优点:观察者和被观察者是抽象耦合的;建立了一套触发机制。
缺点:如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到的话会花费很多时间;如果在观察者和被观察者有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统奔溃。观察者模式没有相应的机制让观察者知道所观察者的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
实例
观察者模式使用三个类Subject、Obeserver和Client.Subject对象带有绑定观察者到Client对象和从Client对象解绑观察者的方法。我们创建Subject类、Oberver抽象类和扩展了抽象类Oberver类的实体类。
public abstract class Observer { protected Subject m_subject; public abstract void Update(); } public class BinaryObserver : Observer { public BinaryObserver(Subject subject) { m_subject = subject; m_subject.Attach(this); } public override void Update() { Console.WriteLine("Binary String:" + m_subject.State.ToString()); } } public class OctalObserver : Observer { public OctalObserver(Subject subject) { m_subject = subject; m_subject.Attach(this); } public override void Update() { Console.WriteLine("Octal String:" + m_subject.State.ToString()); } } public class HexaObserver : Observer { public HexaObserver(Subject subject) { m_subject = subject; m_subject.Attach(this); } public override void Update() { Console.WriteLine("Hex String:" + m_subject.State.ToString()); } } public class Subject { private List<Observer> m_observers = new List<Observer>(); private Int32 m_state; public Int32 State { get { return m_state; } set { m_state = value; NotifyAllObserver(); } } public void NotifyAllObserver() { foreach (var item in m_observers) { item.Update(); } } public void Attach(Observer observer) { m_observers.Add(observer); } }
客户端调用:
static void Main(string[] args) { Console.WriteLine("--------观察者模式---------"); { Subject subject = new Subject(); new HexaObserver(subject); new OctalObserver(subject); new BinaryObserver(subject); Console.WriteLine("First state Change: 15"); subject.State = 15; Console.WriteLine("First state Change: 20"); subject.State = 20; } Console.ReadLine(); }
结果输出: