定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并更新。
观察者模式又叫发布-订阅模式,主要描述了一种目标与观察者之间的相互关系。目标对象一旦发生变化,它所有的观察者都得到通知并作出相应的更新操作。下图恰好描述了这种场景,目标对象拿出烟,观察者纷纷掏出火柴帮忙点烟。
结构分析 UML类图 角色说明Subject
目标类。提供删除、添加观察者的方法,当它的状态发生变化时,向它的观察者发出通知。
Observer
观察者。为具体观察者提供一个统一的更新接口。
ConcreteObserver
具体观察者。实现更新接口,使自身状态与目标一致。
工作原理当目标对象发生改变时,它将通知所有观察者,观察者得到通知后访问目标对象更新状态。
结构代码 //目标类 public class Subject { private List<Observer> _observers = new List<Observer>(); private int _state; public int GetState() { return _state; } public void SetState(int state) { _state = state; Notify(); } public void Attach(Observer observer) { if (!_observers.Contains(observer)) { _observers.Add(observer); } } public void Detach(Observer observer) { if (_observers.Contains(observer)) { _observers.Remove(observer); } } public void Notify() { foreach (var observer in _observers) { observer.Update(); } } } //观察者 public abstract class Observer { protected Subject _subject; public abstract void Update(); } //具体观察者A public class ConcreteObserverA : Observer { public ConcreteObserverA(Subject subject) { _subject = subject; subject.Attach(this); } public override void Update() { Console.WriteLine($"ConcreteObserverA Update State:{_subject.GetState()}"); } } //具体观察者B public class ConcreteObserverB : Observer { public ConcreteObserverB(Subject subject) { _subject = subject; subject.Attach(this); } public override void Update() { Console.WriteLine($"ConcreteObserverB Update State:{_subject.GetState()}"); } } //具体观察者C public class ConcreteObserverC : Observer { public ConcreteObserverC(Subject subject) { _subject = subject; subject.Attach(this); } public override void Update() { Console.WriteLine($"ConcreteObserverC Update State:{_subject.GetState()}"); } } //客户端调用 class Program { static void Main(string[] args) { Subject subject = new Subject(); ConcreteObserverA a = new ConcreteObserverA(subject); ConcreteObserverB b = new ConcreteObserverB(subject); ConcreteObserverC c = new ConcreteObserverC(subject); subject.SetState(200); Console.ReadLine(); } }程序输出
示例分析本节模拟开篇描述的场景,女演员(目标对象)拿出烟,男演员(观察者)为其点烟。首先创建女演员类,包含一个Observer集合用来保存观察者,使用_state字段模拟女演员状态的变化,提供SetState以及GetState存取该状态,并提供Attach和Detach方法添加或删除观察者。
public class Actress { private List<Observer> _observers = new List<Observer>(); private int _state; public int GetState() { return _state; } public void SetState(int state) { _state = state; Notify(); } public void Notify() { foreach (var observer in _observers) { observer.LightCigarette(); } } public void Attach(Observer observer) { if (!_observers.Contains(observer)) { _observers.Add(observer); } } public void Detach(Observer observer) { if (_observers.Contains(observer)) { _observers.Remove(observer); } } }创建观察者,分别实现3个具体观察者。
public abstract class Observer { protected Actress _actress; public abstract void LightCigarette(); } public class ActorA : Observer { public ActorA(Actress actress) { _actress = actress; actress.Attach(this); } public override void LightCigarette() { Console.WriteLine($"ActorA light the cigarette"); } } public class ActorB : Observer { public ActorB(Actress actress) { _actress = actress; actress.Attach(this); } public override void LightCigarette() { Console.WriteLine($"ActorB light the cigarette"); } } public class ActorC : Observer { public ActorC(Actress actress) { _actress = actress; actress.Attach(this); } public override void LightCigarette() { Console.WriteLine($"ActorC light the cigarette"); } }