观察者模式(Observer):在对象间定义一种一对多的依赖关系,以便当某对象的状态改变时,与它存在依赖关系的所有对象都能收到通知并自动进行更新。
基础设计
我们可以使用如下的方式设计一个简单的观察者模式,在被观察者中需要存储一个观察者组,提供一个发送消息的方法对观察组进行消息推送。
在观察者中提供一个消息响应的方法,响应消息。
事件 1 2 3 4 5 6 7 8 public enum Event { 捡到金币, 通关 }
接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public interface IObserver { void OnNotify (Subject subject, Event eventMsg ) ; } public interface ISubject { List<IObserver> Observers () ; void AddObserver (IObserver observer ) ; void RemoveObserver (IObserver observer ) ; }
实体对象 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 public class Observer : IObserver { public void OnNotify (Subject subject, Event eventMsg ) { switch (eventMsg) { case Event.捡到金币: subject.Score += 10 ; break ; case Event.通关: subject.Score += 100 ; break ; } } } public class Subject : ISubject { public int Score; private readonly List<IObserver> _observers; public void Notify (Event eventMsg ) { _observers.ForEach(x=>x.OnNotify(this ,eventMsg)); } public Subject () { _observers = new List<IObserver>(); } public List<IObserver> Observers () { return _observers; } public void AddObserver (IObserver observer ) { _observers.Add(observer); } public void RemoveObserver (IObserver observer ) { _observers.Remove(observer); } }
使用委托和事件 在Csharp中内置了委托和事件来处理这种一对多的响应方式。
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 using System;namespace ObserverPattern { internal static class Program { public static void Main (string [] args ) { var c = new Cat() {Name = "小白" }; var m = new Mouse(c) {Name = "小鼠" }; c.OnCatCom(); } } class Cat { public string Name { get ; set ; } public event Action catCom; public virtual void OnCatCom () { Console.WriteLine("{0}来了" ,Name); catCom?.Invoke(); } } class Mouse { public string Name { get ; set ; } public Mouse (Cat cat ) { cat.catCom += this .MouseRun; } private void MouseRun () { Console.WriteLine("{0}快跑!!" ,Name); } } }
思考 其实观察者模式就是对象的一种间接同步调用,使用这种方法是为了解除耦合,达到统一分配管理的作用。
从上文提到的可以知道,这种模式是同步的,也就是说当存在一组观察者时,那么可能会导致阻塞,但在实际中可能没这么严重,但在使用中我们还需注意。
如果你在每次响应后给出一个状态,表示通知的响应情况,那么这就接近 责任链模式了。
销毁对象? 在书中提到一个问题很有趣,在观察者模式中销毁对象该怎么办呢?
在销毁对象前,需要解除监听,确保对象被正确销毁。
现状
观察者模式出现于1994年(比我还大:smile:),因此基本都是基于类来实现的,但现在更流行函数式编程,可能不太符合现在的编程美学。例如C#的event就是现代化的观察者模式。