设计模式之四 观察者模式(Observer Pattern)
概述
观察者模式定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题,这个主题对象在状态变化时,会通知所有的观察者对象,使它们能够自动更新自己。
结构图
对应的代码
class Program { static void Main(string[] args) { ConcreteSubject s = new ConcreteSubject(); s.Attach(new ConcreteObserver(s, "X")); s.Attach(new ConcreteObserver(s, "Y")); s.Attach(new ConcreteObserver(s, "Z")); s.SubjectState = "ABC"; s.Notify(); Console.Read(); } } abstract class Subject { private IList<Observer> observers = new List<Observer>(); //增加观察者 public void Attach(Observer observer) { observers.Add(observer); } //移除观察者 public void Detach(Observer observer) { observers.Remove(observer); } //通知 public void Notify() { foreach (Observer o in observers) { o.Update(); } } } //具体通知者 class ConcreteSubject : Subject { private string subjectState; //具体通知者状态 public string SubjectState { get { return subjectState; } set { subjectState = value; } } } abstract class Observer { public abstract void Update(); } class ConcreteObserver : Observer { private string name; private string observerState; private ConcreteSubject subject; public ConcreteObserver( ConcreteSubject subject, string name) { this.subject = subject; this.name = name; } //更新 public override void Update() { observerState = subject.SubjectState; Console.WriteLine("观察者{0}的新状态是{1}", name, observerState); } public ConcreteSubject Subject { get { return subject; } set { subject = value; } } }
运行结果
1:例如:我门很多人在网上关注了一台智能手机(苹果的),当手机的价格等任何状态改变时,苹果公司都会通过电话短信、邮件、告之我们客户
2:在一个快递公司来了很多包裹,工作人员发短信、打电话通知我们去那快递等。
3:银行卡在自助终端取钱时取了钱,银行会通过短信、邮件方式提醒我们等等生活中有很多这样的实例。
用事件和委托来实现Observer模式我认为更加的简单和优雅,也是一种更好的解决方案。
在观察者模式中我们不能紧紧依赖一个固定的观察者来通知自己发生变化后引起依赖它的对象的状态的改变,进一步的深入学习我们引入事件委托来解决问题。下面的例子简单的用事件和委托实现如下,仅供大家参考:
class Program { static void Main(string[] args) { //老板胡汉三 Boss huhansan = new Boss(); //看股票的同事 StockObserver tongshi1 = new StockObserver("魏关姹", huhansan); //看NBA的同事 NBAObserver tongshi2 = new NBAObserver("易管查", huhansan); huhansan.Update += new EventHandler(tongshi1.CloseStockMarket); huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding); //将两个不同类的不同方法委托给老板类的更新了 //老板回来 huhansan.SubjectState = "我胡汉三回来了!"; //发出通知 huhansan.Notify(); Console.Read(); } } //通知者接口 interface Subject { void Notify(); string SubjectState { get; set; } } //事件处理程序的委托 delegate void EventHandler(); class Secretary : Subject { //声明一事件Update,类型为委托EventHandler public event EventHandler Update; private string action; public void Notify() { Update(); } public string SubjectState { get { return action; } set { action = value; } } } class Boss : Subject { //声明一事件Update,类型为委托EventHandler public event EventHandler Update; //声明一EventHandler事件处理程序的委托事件,名称为Update更新 private string action; public void Notify() { Update();//在访问通知方法时,调用更新 } public string SubjectState { get { return action; } set { action = value; } } } //看股票的同事 class StockObserver { private string name; private Subject sub; public StockObserver(string name, Subject sub) { this.name = name; this.sub = sub; } //关闭股票行情 public void CloseStockMarket()//方法“更新”名改为“关闭股票程序” { Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SubjectState, name); } } //看NBA的同事 class NBAObserver { private string name; private Subject sub; public NBAObserver(string name, Subject sub) { this.name = name; this.sub = sub; } //关闭NBA直播 public void CloseNBADirectSeeding()//方法改为关闭NBA直播 { Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name); } }使用观察者模式的时机
1:当一个抽象模型有两个方面,其中一个方面依赖于另一方面,这将二者封装在独立的对象中以使它们可以各自独立地改变和复用。
2:当一个对象的改变同时改变其他对象,而不知道具体有多少对象有待改变。
3:当一个对象必须通知其他对象,而它又不能假定其他对象是谁,换言之,不希望这些对象是紧密耦合的。
总结通过Observer Pattern模式,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。