Observer 与 Subject 互为耦合,但是这种耦合的双方都依赖于抽象,而不依赖于具体。
一、观察者模式
目的
我们都知道解决一个问题有N种解决方式,但在面向对象的设计中如何能做到“高内聚,低耦合”,设计可重用的对象才是我们追求的。在设计过程中,我们经常会接触到一种情况:一个对象的行为引发其它多个对象相应的行为。这时我们便可以通过观察者模式的设计思想来设计对象模型。
概述
观察者模式(Observer Pattern)是设计模式中行为模式的一种,它解决了上述具有一对多依赖关系的对象的重用问题。此模式的参与者分为两大类,一类是被观察的目标,另一类是观察该目标的观察者们。正因为该模式是基于“一对多”的关系,所以该模式一般是应用于由一个目标对象和N个观察者对象组成(当然也可以扩展为有多个目标对象,但我们现在只讨论前者)的场合。当目标对象的状态发生改变或做出某种行为时,正在观察该目标对象的观察者们将自动地、连锁地作出相应的响应行为。
原理
我们可以把观察目标理解为主动方、发布方、主体等;把观察者理解为被动方、订阅方、观察器等。目标是整个行为链的源头,其它观察者都依赖于它的变化而作出响应。为了实现低耦合,我们不能使用“直接调用”的方式而需要利用“订阅(清单)-通知”的机制去完成设计。通俗地说就是观察者向目标“订阅”它的改变,而目标发生改变后就“通知”所有已经“订阅”了它的改变的观察者,从而执行“订阅”的内容。这种机制的好处在于降低耦合度,分工明确,目标只负责在自身状态发生改变或做出某种行为时向自身的订阅清单发出“通知”,而不是直接调用观察者的行为(方法);观察者只负责向目标“订阅”它的变化,以及定义自身在收到目标“通知”后所需要做出的具体行为(也就是订阅的内容)。就像我们向出版社订阅报刊一样,出版社有新一期报刊发行时并不是直接跟每位订阅者联系,而是“通知”订阅者名单按顺序给每位订阅者发送所订报刊。
二、C#中的观察者模式
概述
每种编程架构及程序语言,对观察者模式都有不通的具体实现。在.NET框架中,C#语言使用委托以及事件,可以很好的实现观察者模式。委托相当于“订阅清单”的角色,当目标中关联了该委托的事件被触发时,则委托将自动按序执行观察者注册于委托中的方法。
模型与观察者基类
我们把观察者模式的参与者都描述为派生自模型及观察者二个抽象基类的类。模型规划了事件,而观察者则规划了订阅及行为。
模型需要做的只是声明委托以及声明委托类型的事件。当然,还可以附加上封装了触发委托事件的方法。所有派生自模型的类都是具体目标,它们所要做的只是在适当的场合触发事件。(即发出“通知”)。
在观察者基类中,我们通过构造器将抽象的响应方法注册(订阅)于委托事件中。所有派生自观察者基类的类都是具体观察者。因为订阅行为已经在抽象基类完成,具体观察者需要做的只是通过覆盖观察者基类的方法去定义具体需要响应的行为,和通过构造器把需要观察的具体目标传递给基类构造器。
优点
通过对模型与观察者基类的分析可知,委托与事件的机制几乎消除了这两个模块之间的耦合,灵活性提高了很多。如果需要增加观察者,则只需要覆盖基类抽象方法及把观察目标传递给基类。
代码实现如下
方式一:
public class OberverMode { public OberverMode() { var _var = new Cat(); Mouse mouse = new Mouse("老猫..", _var); Mouse mouse1 = new Mouse("土拨鼠", _var); People people = new People("张三丰", _var); Baby baby = new Baby("朱丽叶", _var); _var.Miao(); Console.ReadKey(); } public abstract class ModelBase { public delegate void ModeEventHandler(); public event ModeEventHandler _ModeEvent; protected void Notifytion() { if (_ModeEvent != null) { _ModeEvent?.Invoke(); } } } public abstract class Observer1 { protected Observer1(ModelBase modelBase) { modelBase._ModeEvent += new ModelBase.ModeEventHandler(Response1); } public abstract void Response1(); } public abstract class Observer2 { protected Observer2(ModelBase @base) { @base._ModeEvent += new ModelBase.ModeEventHandler(Response1); @base._ModeEvent += new ModelBase.ModeEventHandler(Response2); } public abstract void Response1(); public abstract void Response2(); } public class Cat : ModelBase { public void Miao() { Console.WriteLine("cat is miao ..."); this.Notifytion(); } } public class Mouse : Observer1 { private string Name; public Mouse(string name, ModelBase modelBase) : base(modelBase) { Name = name; } public override void Response1() { Console.WriteLine(Name + "跑了、、、、"); } } public class People : Observer1 { private string _Name; public People(string name,ModelBase modelBase):base(modelBase) { _Name = name; } public override void Response1() { Console.WriteLine(_Name + "人来了、、、"); } } public class Baby : Observer2 { public string _name; public Baby(string name, ModelBase modelBase) : base(modelBase) { _name = name; } public override void Response1() { Console.WriteLine(_name + "醒了、、、"); } public override void Response2() { Console.WriteLine(_name + "还哭了、、、"); } } }
方式二:
class Program { static void Main(string[] args) { Cat cat = new Cat(); People people = new People(); Mouse mouse = new Mouse(); cat.evter += new CatHand(people.Coming); cat.evter += new CatHand(mouse.Runfaster); cat.CatHandup(); } } public delegate void CatHand(); public class Cat { public event CatHand evter; public void CatHandup() { Console.WriteLine("cat is hand "); evter?.Invoke(); } } public class People { public void Coming() { Console.WriteLine("人来了... "); } } public class Mouse { public void Runfaster() { Console.WriteLine("赶紧跑... "); } }
以上内容为观察这模式实现的两种方式;
欢迎斧正!