1.1 意图
定义对象间一对多的依赖关系,一个对象发生变化时,所有依赖它的对象都得到通知并被自动更新。Windows中的音量控制就是一个很典型的例子,可以找开多个调节音量的窗口,但注意观察可发现,当你在其中一个窗口中调节音量,其它窗口也会做出相关改变。这是因为每个窗口都定阅了音最大小这一实例的值,所以当音量大小改变时,它们就改变窗口中的显示状态。
1.2 使用场合
观察者设计模式适当以下情形适用:
A.当一个抽象模型有两个方面,其中一个方面依赖开另一方面,将这二者封装在独立的对象中以使它们可以独立的改变和复用,降低它们这间的耦合性。
B.改变一个对象需要同时改变其它对象,但不知道有多少个对象有待改变。
1.3 静态结构图
观察者设计模式结构图如下:
A. Subject:目标对象(接口或抽象类接供规范),即被观察的对象,要以有任意多个观察者观察一个目标。
B. Observer::观察者对象(接口或抽象类接供规范),为观察者定义一个更新的接口.
C. ConcreateSubject : 具体的目标继承于目标抽象类或接口,当目标信息发生变化时通知所有具体的观察者。
D. ConcreteObersever :具体的观察者继承于观察者抽象类或接口,依懒于具体的目标对象,根据具体目标信息更新具体的观察者。
接着据于一个简单的场景来DEMO一下观察者设计模式的使用。设计模式在实现时,它只是一种规范,实现起来应该是很灵活的,在此只抛下砖吧,如果有引玉的效果那是最好不过了。
场景:一家公司有很多客户,当公司的信息发生变化时,客户也会及时的更新该公司的信息,在这个例子里就把它打印出来吧!
1.4 代码
2 {
3 class Program
4 {
5 #region 公司目标抽象类
6 public abstract class CompanyObject
7 {
8 ArrayList observers = new ArrayList();
9 public void Attach(CustomerObserver observer)
10 {
11 observers.Add(observer);
12 }
13 public void Detach(CustomerObserver observer)
14 {
15 observers.Remove(observer);
16 }
17 public void Notify(string information)
18 {
19 foreach (CustomerObserver observer in observers)
20 {
21 observer.Update(information);
22 }
23 }
24 }
25 #endregion
26 #region 客户观察者抽象类
27 public abstract class CustomerObserver
28 {
29 public abstract void Update(string information );
30
31 }
32 #endregion
33 #region 具体的目标公司对象
34 public class ConcreteCompanyObject : CompanyObject
35 {
36 string information = null;
37
38 public ConcreteCompanyObject()
39 {
40
41 }
42 public void ChangeInformation(string info)
43 {
44 this.information = info;
45 this.Notify(info);
46 }
47
48 }
49 #endregion
50 #region 具体的客户观察对象
51 public class ConcreteCustomerObserver : CustomerObserver
52 {
53 string name = null;
54
55 public ConcreteCustomerObserver(string name)
56 {
57 this.name = name;
58 }
59
60 public string Name
61 {
62 set { this.name = value; }
63 get { return this.name; }
64 }
65 public override void Update(string info)
66 {
67 this.Print(info);
68 }
69 private void Print(string info)
70 {
71 Console.WriteLine("名为{0}更新了合作公司的信息。信息内容为:{1}", name, info);
72
73 }
74
75 }
76 #endregion
77
78 #region 测试类
79 static void Main(string[] args)
80 {
81 //创建一个公司实例
82 ConcreteCompanyObject company = new ConcreteCompanyObject();
83 //创建两个客户实例
84 ConcreteCustomerObserver customer1 = new ConcreteCustomerObserver("First");
85 ConcreteCustomerObserver customer2 = new ConcreteCustomerObserver("Second");
86
87 //给两个客户订阅信息
88 company.Attach(customer1);
89 company.Attach(customer2);
90 //更改公司信息
91 company.ChangeInformation("合作愉快!");
92 //预测:两个客户将打印相关信息
93
94 Console.Read();
95 }
96 #endregion
97 }
98 }
99
1.5 .NET中采用委托和事件机制简化观察者模式的实现
委托和事件机制使得目标对象不需要知道观察者对象的存在,观察者若需要及时知道目标状态的变化,就得通过事件来定阅,并具体实现委托事件来达到更新观察者。
例如上面的例子,客户最终的目的就是显示合作公司的信息改变(如商品的库存情况的变化),用委托和事件机制来实现上面的场景,看看是不是简化灵活了许多。
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace ConObserver
6 {
7 public class Companys
8 {
9 string information = null;
10 public delegate void ReportChange(string info);
11 public event ReportChange changeInfo;
12 public Companys()
13 {
14
15 }
16 public void ChangeInfomation(string info)
17 {
18 this.information = info;
19 //执行信息改变事件
20 changeInfo(info);
21 }
22 }
23 public class Customer
24 {
25 Companys company ;
26 public Customer()
27 {
28
29 }
30 public void InitCompanyObject(Companys com)
31 {
32 this.company = com;
33 //定阅合作公司信息改变事件
34 com.changeInfo += new Companys.ReportChange(com_changeInfo);
35 }
36 //公司信息改变委托办法
37 void com_changeInfo(string info)
38 {
39 //执行打印信息。
40 this.Print(info);
41 }
42 private void Print(string info)
43 {
44 Console.WriteLine("名为{0}更新了合作公司的信息。信息内容为:{1}", name, info);
45
46 }
47 }
48
49 }