设计模式-行为型-观察者模式

观察者模式(Observer):

  指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式的角色:

  

  1)抽象目标(Subject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

  2)具体目标(ConcreteSubject):也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。

  3)抽象观察者(Observer):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。

  4)具体观察者(ConcreteObserver):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

1 internal class Program
 2 {
 3     private static void Main(string[] args)
 4     {
 5         Subject subject = new ConcreteSubject();
 6         Observer observer1 = new ConcreteObserver1();
 7         Observer observer2 = new ConcreteObserver2();
 8         subject.Attach(observer1);
 9         subject.Attach(observer2);
10         subject.Notify();
11     }
12 }
13
14 /// <summary>
15 /// 抽象目标
16 /// </summary>
17 internal abstract class Subject
18 {
19     /// <summary>
20     /// 新增观察者
21     /// </summary>
22     /// <param name="o"></param>
23     public abstract void Attach(Observer o);
24
25     /// <summary>
26     /// 删除观察者
27     /// </summary>
28     /// <param name="o"></param>
29     public abstract void Detach(Observer o);
30
31     /// <summary>
32     /// 通知观察者
33     /// </summary>
34     public abstract void Notify();
35 }
36
37 /// <summary>
38 /// 抽象观察者
39 /// </summary>
40 internal abstract class Observer
41 {
42     public abstract void update();
43 }
44
45 /// <summary>
46 /// 具体目标
47 /// </summary>
48 internal class ConcreteSubject : Subject
49 {
50     private System.Collections.Generic.List<Observer> observers
51         = new System.Collections.Generic.List<Observer>();
52
53     public override void Attach(Observer o)
54     {
55         if (o != null)
56             observers.Add(o);
57     }
58
59     public override void Detach(Observer o)
60     {
61         if (o != null)
62             observers.Remove(o);
63     }
64
65     public override void Notify()
66     {
67         Console.WriteLine("目标发生变化");
68         foreach (var observer in observers)
69         {
70             observer.update();
71         }
72     }
73 }
74
75 /// <summary>
76 /// 具体观察者1
77 /// </summary>
78 internal class ConcreteObserver1 : Observer
79 {
80     public override void update()
81     {
82         Console.WriteLine("观察者1更新");
83     }
84 }
85
86 /// <summary>
87 /// 具体观察者2
88 /// </summary>
89 internal class ConcreteObserver2 : Observer
90 {
91     public override void update()
92     {
93         Console.WriteLine("观察者2更新");
94     }
95 }

事例:

  学校的“铃”是事件源和目标,"学生"是事件监听器和具体观察者,"铃声"是事件类。当下课时间到,会触发铃发声,这时会生成“铃声”事件;学生就会做一些事情。。。

1 internal class Program
  2 {
  3     private static void Main(string[] args)
  4     {
  5         // 创建下课铃声
  6         Bell subject = new FinishClassBell();
  7         // 创建观察者
  8         Observer xiaoming = new XiaoMing();
  9         Observer xiaohong = new XiaoHong();
 10         Observer xiaowang = new XiaoWang();
 11         // 观察者随着听着下课铃
 12         subject.Attach(xiaoming);
 13         subject.Attach(xiaohong);
 14         subject.Attach(xiaowang);
 15         // 下课铃响了,通知大家
 16         subject.Notify();
 17     }
 18 }
 19
 20 /// <summary>
 21 /// 铃声:抽象目标
 22 /// </summary>
 23 internal abstract class Bell
 24 {
 25     /// <summary>
 26     /// 新增观察者
 27     /// </summary>
 28     /// <param name="o"></param>
 29     public abstract void Attach(Observer o);
 30
 31     /// <summary>
 32     /// 删除观察者
 33     /// </summary>
 34     /// <param name="o"></param>
 35     public abstract void Detach(Observer o);
 36
 37     /// <summary>
 38     /// 通知观察者
 39     /// </summary>
 40     public abstract void Notify();
 41 }
 42
 43 /// <summary>
 44 /// 同学下课做事情:抽象观察者
 45 /// </summary>
 46 internal abstract class Observer
 47 {
 48     public abstract void DoSomeThings();
 49 }
 50
 51 /// <summary>
 52 /// 下课铃声:具体目标
 53 /// </summary>
 54 internal class FinishClassBell : Bell
 55 {
 56     private System.Collections.Generic.List<Observer> observers
 57         = new System.Collections.Generic.List<Observer>();
 58
 59     public override void Attach(Observer o)
 60     {
 61         if (o != null)
 62             observers.Add(o);
 63     }
 64
 65     public override void Detach(Observer o)
 66     {
 67         if (o != null)
 68             observers.Remove(o);
 69     }
 70
 71     public override void Notify()
 72     {
 73         Console.WriteLine("铃声响了...");
 74         foreach (var observer in observers)
 75         {
 76             observer.DoSomeThings();
 77         }
 78     }
 79 }
 80
 81 /// <summary>
 82 /// 小明同学
 83 /// </summary>
 84 internal class XiaoMing : Observer
 85 {
 86     public override void DoSomeThings()
 87     {
 88         Console.WriteLine("小明同学:下课打篮球");
 89     }
 90 }
 91
 92 /// <summary>
 93 /// 小红同学
 94 /// </summary>
 95 internal class XiaoHong : Observer
 96 {
 97     public override void DoSomeThings()
 98     {
 99         Console.WriteLine("小红同学:呜呜呜,还有一节课");
100     }
101 }
102
103 /// <summary>
104 /// 小王同学
105 /// </summary>
106 internal class XiaoWang : Observer
107 {
108     public override void DoSomeThings()
109     {
110         Console.WriteLine("小王同学:饿死了,开吃...");
111     }
112 }

观察者模式的应用场景:

  1)对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。

  2)当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

观察者模式的优缺点:

  优点:观察者和被观察者是抽象耦合的;建立的一套触发机制。

  缺点:

    1)如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    2)如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

    3)观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

.NET中观察者模式的应用:

1 // 委托充当订阅者接口类
 2 public delegate void NotifyEventHandler(object sender);
 3
 4 // 抽象订阅号类
 5 public class TenXun
 6 {
 7     public NotifyEventHandler NotifyEvent;
 8
 9     public string Symbol { get; set; }
10     public string Info { get; set; }
11     public TenXun(string symbol, string info)
12     {
13         this.Symbol = symbol;
14         this.Info = info;
15     }
16
17     // 新增对订阅号列表的维护操作
18     public void AddObserver(NotifyEventHandler ob)
19     {
20         NotifyEvent += ob;
21     }
22     // 删除对订阅号列表的维护操作
23     public void RemoveObserver(NotifyEventHandler ob)
24     {
25         NotifyEvent -= ob;
26     }
27     // 推送消息
28     public void Update()
29     {
30         if (NotifyEvent != null)
31         {
32             NotifyEvent(this);
33         }
34     }
35 }
36
37 // 具体订阅号类
38 public class TenXunGame : TenXun
39 {
40     public TenXunGame(string symbol, string info)
41         : base(symbol, info)
42     {
43     }
44 }
45
46 // 具体订阅者类
47 public class Subscriber
48 {
49     public string Name { get; set; }
50     public Subscriber(string name)
51     {
52         this.Name = name;
53     }
54
55     public void ReceiveAndPrint(Object obj)
56     {
57         TenXun tenxun = obj as TenXun;
58
59         if (tenxun != null)
60         {
61             Console.WriteLine("Notified {0} of {1}'s" + " Info is: {2}", Name, tenxun.Symbol, tenxun.Info);
62         }
63     }
64 }
65
66 static void Main(string[] args)
67 {
68     TenXun tenXun = new TenXunGame("TenXun Game", "Have a new game published ....");
69     Subscriber lh = new Subscriber("Learning Hard");
70     Subscriber tom = new Subscriber("Tom");
71
72     // 添加订阅者
73     tenXun.AddObserver(new NotifyEventHandler(lh.ReceiveAndPrint));
74     tenXun.AddObserver(new NotifyEventHandler(tom.ReceiveAndPrint));
75     tenXun.Update();
76
77     Console.WriteLine("-----------------------------------");
78     Console.WriteLine("移除Tom订阅者");
79     tenXun.RemoveObserver(new NotifyEventHandler(tom.ReceiveAndPrint));
80     tenXun.Update();81 }

  从上面代码可以看出,使用事件和委托实现的观察者模式中,减少了订阅者接口类的定义,此时,.NET中的委托正式充到订阅者接口类的角色。使用委托和事件,确实简化了观察者模式的实现,减少了一个IObserver接口的定义。

参考:https://www.cnblogs.com/zhili/p/ObserverPattern.html

(0)

相关推荐

  • C#之winform捕获Console.WriteLine内容到日志文件

    问题描述 之前接手同事的项目,是一个类似于服务端后台的Winform程序,主界面隐藏起来,只再任务栏显示程序图标. 整个项目里面没有日志记录功能,全靠Console.WriteLine打印信息.自己调 ...

  • 行为型模式之观察者模式

    在现实世界中,许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变.例如,某种商品的物价上涨时会导致部分商家高兴,而消费者伤心. 在软件世界也是这样,例如 ...

  • 设计模式(20) 观察者模式

    观察者模式是一种平时接触较多的模式.它主要用于一对多的通知发布机制,当一个对象发生改变时自动通知其他对象,其他对象便做出相应的反应,同时保证了被观察对象与观察对象之间没有直接的依赖. GOF对观察者模 ...

  • 使用C#的计时器加观察者模式完成报警推送需求

    前言 这两天面试了一个物联网公司高级研发,面试题是下面这样子 公司领导,部门主管,小组组长,组成员4级,假如有个 疫情预警,先通知组人员(对个人,主要有一个处理就算处理了) 如果3分钟没处理,就往组长 ...

  • 设计模式-行为型-访问者模式

    访问者模式(Vistor): 访问者模式的官方定义是这样的:表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作.官方的东西总是晦涩难懂的,那么我们现 ...

  • 设计模式-行为型-中介者模式

    中介者模式(Mediator): 在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群.短信平台和房产中介.不论是QQ游戏还是QQ群,它们都是充当一个中间平台,QQ用户可以登录这个中 ...

  • 设计模式-行为型-状态模式

    状态模式(State): 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到,然后使用if else语句来做状态判断来进行不同情况的处理 ...

  • 设计模式-行为型-模板模式

    模板模式(Template): 提到模板,可能大多数人想到的是"简历模板"."论文模板"等,比如我们要写简历时,会从网上下载一份漂亮的简历模板,其格式是固定的, ...

  • 设计模式-创建型-建造者模式

    引言: 无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮.底盘.发动机.方向盘等各种部件.而对于大部分用户而言,无须知道这些部件的装配细节,也几乎不会 ...

  • 设计模式-创建型-抽象工厂模式

    前一章节,我们介绍了简单工厂模式以及工厂方法模式,但是这两种模式都存在一定的局限性,只能生产某一类型下的某一种产品,如果需求变更,同类型下出现了不同的产品,比如芝士披萨不仅有口味上的不同,同时存在外观 ...

  • 设计模式-创建型-工厂模式

    工厂设计模式: 顾名思义,该模式是用来生产对象的.在面向对象的设计模式中,万物皆对象,若使用new来创建对象,就会对该对象产生强耦合,假如我们需要更换该对象,那么使用该对象的对象都需要进行修改,这显然 ...

  • 设计模式-创建型-单例模式

    前言: 单例模式,顾名思义,只存在一个实例.官方定义:对于类的单例模式设计,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法). ...

  • 设计模式中的观察者模式

    观察者模式是一种软件设计模式,其中一个名为主体(Subject)的对象维护其依赖项列表,称为观察者,并通常通过调用它们(observers)的方法之一来自动通知它们任何状态更改. 观察者模式主要用于在 ...