5. 观察者模式(Observer Pattern)
一、介绍
话说啊,我们公司小王上班期间总爱玩游戏,当然是在老板不在的时候了;但是呀,这家伙运气不好,总被老板抓,这天呢老板又出去了,他想到个好主意,我看到老板回来后立即在扣扣中提前震动他一下(由于我的座位更靠近门,老板来了我会第一个发现),让他知道老板要来,以免被抓。你会说这小王很聪明啊,是啊他刚好用到了我们设计模式中的一种 —— 观察者模式。观察者模式,又叫发布-订阅(Publish/Subscribe)模式,大家仔细回想小王这件事,抽象开来,“老板回来”这是一件事,我呢是受委托人,小王是委托人,这里又要用到面向对象的两个技术 委托和事件,对着俩个家伙还不了解,出门左转见这两篇文章附录一 面向对象基础 以及 C# 中的委托和事件 ,接下来我们说一下 观察者模式。
二、UML图


三、总结
1. 定义:观察者模式定义了一种一对多的关系,让多个观察者对象同时监听某一个主体对象,当主题对象的状态发生变化时, 会通知所有观察者,使得他们能做出相应的更新。
2. 实现:
Subject 是主题或者统治者,他把所有观察者的引用保存到一个聚集里,当自身状态发生改变时,方便通知所有的观察者。
Observer 为观察者,一般为抽象类或者接口,通常包含一个类似 Update() 方法。
3. 使用场景:
⑴ 当一个对象的改变,需要同时改变其他对象时,而且他不知道有多少对象有待改变时,可以考虑使用观察者模式
⑵ 一个抽象模型有两方面,其中一方面依赖于另一方面,这时可以考虑使用观察者模式,将二者封装到独立的对象中
4. 委托与事件:
委托可以看做是声明了一个特殊的类,事件可以看做是声明了一个委托的变量
委托所搭载的所有方法必须具有原型和返回形式,也就是拥有相同的参数和返回值类型
5. 不足:(这只是观察者模式的一种实现,具体场景可能需要变形,但万变不离其宗)
四、附录
Subject 类:
public class Subject { /// <summary> /// 声明一个特殊的“类”(委托类) /// </summary> public delegate void EventHandler(); /// <summary> /// 声明一个事件委托变量 /// </summary> private event EventHandler Update; /// <summary> /// 绑定观察者 /// </summary> /// <param name="handler">操作</param> public void Attach(EventHandler handler) { Update += handler; } /// <summary> /// 移除绑定 /// </summary> /// <param name="handler">操作</param> public void DeAttach(EventHandler handler) { Update -= handler; } /// <summary> /// 通知观察者 /// </summary> public void Notify() { if (null != Update) Update(); } }
Observer 类:
public abstract class Observer { /// <summary> /// 名字 /// </summary> protected string Name { get; set; } /// <summary> /// 构造初始化 /// </summary> /// <param name="name"></param> protected Observer(string name) { this.Name = name; } /// <summary> /// 观察者采取行动 /// </summary> public abstract void Update(); }
Observer 具体类1:
public class GamePlayerObserver:Observer { public GamePlayerObserver(string name) : base(name) { } /// <inheritdoc /> public override void Update() { Console.WriteLine("我是"+this.Name+"老板来了,不玩游戏了,我要工作了"); } }
Observer 具体类2:
public class NbaWatcherObserver:Observer { public NbaWatcherObserver(string name) : base(name) { } public override void Update() { Console.WriteLine("我是"+this.Name+"老板来了,不看NBA了,我要工作了"); } }
客户端:
internal class Program { private static void Main(string[] args) { //委托人 var xiaozhang = new Subject(); xiaozhang.Attach(new GamePlayerObserver("小王").Update); xiaozhang.Attach(new NbaWatcherObserver("小赵").Update); //时间在一分一秒的故去 for (int i = 0; i < 100; i++) { Thread.Sleep(100); if (i < 75) { Console.WriteLine("现在时刻" + i); } //老板来了 else if (i == 75) { xiaozhang.Notify(); } } } }
真正的大师永远怀着一颗学徒的心。

浙公网安备 33010602011771号