引言
在现实生活中,处处可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用。在这一章将分享我对观察者模式的理解,废话不多说了,直接进入今天的主题。
观察者模式的介绍
2.1 观察者模式的定义
从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户。从中,我们就可以得出观察者模式的定义。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为。
2.2 观察者模式的结构图
可以看出,在观察者模式的结构图有以下角色:
- 抽象主题角色(Subject):抽象主题把所有观察者对象的引用保存在一个列表中,并提供增加和删除观察者对象的操作,抽象主题角色又叫做抽象被观察者角色,一般由抽象类或接口实现。
- 抽象观察者角色(Observer):为所有具体观察者定义一个接口,在得到主题通知时更新自己,一般由抽象类或接口实现。
- 具体主题角色(ConcreteSubject):实现抽象主题接口,具体主题角色又叫做具体被观察者角色。
- 具体观察者角色(ConcreteObserver):实现抽象观察者角色所要求的接口,以便使自身状态与主题的状态相协调。
2.3观察者模式的实现
下面我们已抖音为例,当你刷抖音时候,看到一个很不错的小视频,就关注了这个作者,以后作者每次更新视频的时候,系统都会给关注他的粉丝推送新的消息,下面是我写的第一版实现代码:
////// 作者 /// public class OAuth { private Listlist = new List (); public string name { get; set; } /// /// 新增一个粉丝 /// /// public void Add(Fans add) { list.Add(add); } ////// 减少一个粉丝 /// /// public void Remove(Fans remove) { list.Remove(remove); } public void Nofify() { foreach (Fans item in list) { item.Update(); } } } ////// 粉丝 /// public class Fans { private string name; private OAuth sub; public Fans(string name, OAuth sub) { this.name = name; this.sub = sub; } public void Update() { Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看",name,sub.name); } } ////// 客户端 /// class Program { static void Main(string[] args) { OAuth oauth = new OAuth(); oauth.name = "小炒肉"; Fans a = new Fans("青椒",oauth); Fans b = new Fans("胡萝卜",oauth); oauth.Add(a); oauth.Add(b); oauth.Nofify(); Console.ReadLine(); } } //结果显示 你好:青椒,小炒肉发布了新的作品,点击查看 你好:胡萝卜,小炒肉发布了新的作品,点击查看
看到这种代码我们首先想到的是 违反了面向对象的开发-封闭原则,其次是依赖倒转原则,类与类之间不应该相互依赖,而应该依赖与抽象,好了,我们得重新修改了,10分钟后第二版出来了
public abstract class Observer { protected string name; protected Subject sub; public Observer(string name, Subject sub) { this.name = name; this.sub = sub; } public abstract void Update(); } public class Person : Observer { public Person(string name, Subject sub) : base(name, sub) { } public override void Update() { Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看", name, sub.name); } } public abstract class Subject { public string name { get; set; } public abstract void Add(Observer ob); public abstract void Remove(Observer ob); public abstract void Notify(); } public class Green : Subject { private Listlist = new List (); public override void Add(Observer ob) { list.Add(ob); } public override void Notify() { foreach (var item in list) { item.Update(); } } public override void Remove(Observer ob) { list.Remove(ob); } } /// /// 客户端 /// class Program { static void Main(string[] args) { Subject ob = new Green(); ob.name = "小炒肉"; Observer a = new Person("青椒", ob); Observer b = new Person("胡萝卜", ob); ob.Add(a); ob.Add(b); ob.Notify(); Console.ReadLine(); } } ///结果你好:青椒,小炒肉发布了新的作品,点击查看你好:胡萝卜,小炒肉发布了新的作品,点击查看
现在已经依赖接口编程,但是“抽象通知者”还是依赖 抽象观察者,也就是说,万一没有了抽象观察者这样的接口,我这通知的功能就完成不了,下面我们引入委托解耦实现通知者和观察者
public class Person { protected string name; protected Subject sub; public Person(string name, Subject sub) { this.name = name; this.sub = sub; } public void UpdateTP() { Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看", name, sub.name); } } public delegate void EventHandler(); public interface Subject { string name { get; set; } void Notify(); } public class Green : Subject { public event EventHandler Update; public string name { get; set; } public void Notify() { Update(); } } ////// 客户端 /// class Program { static void Main(string[] args) { Green hand = new Green(); hand.name = "小王"; Person per = new Person("青椒",hand); Person Ge = new Person("小炒肉", hand); hand.Update += new EventHandler(per.UpdateTP); hand.Update += new EventHandler(Ge.UpdateTP); hand.Notify(); Console.ReadLine(); } }
总结
在C#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。
好了在次复习下,观察者模式的定义,观察者模式定义了一种一对多的关系,让多个观察者对象可以同时监听某一个主题对象,这个主题对象在发送状态改变时,会通知所有观察者对象,时它们能够自动更新自己