1. 程式人生 > >C#設計模式--觀察者模式(發布-訂閱模式)

C#設計模式--觀察者模式(發布-訂閱模式)

工廠方法 設計 解決 line strac itl names spa ret

0.C#設計模式--簡單工廠模式

1.C#設計模式--工廠方法模式

2.C#設計模式--抽象工廠模式

3.C#設計模式--單例模式

4.C#設計模式--建造者模式

5.C#設計模式--原型模式

6.C#設計模式--設配器模式

7.C#設計模式--裝飾器模式

8.C#設計模式--代理模式

9.C#設計模式--外觀模式

10.C#設計模式--橋接模式

設計模式:

觀察者模式(Observer Pattern)

簡單介紹:

  觀察者模式(Observer Pattern)是設計模式中行為模式的一種,它解決了上述具有一對多依賴關系的對象的重用問題。此模式的參與者分為兩大類,一類是被觀察的目標,另一類是觀察該目標的觀察者們。正因為該模式是基於“一對多”的關系,所以該模式一般是應用於由一個目標對象和N個觀察者對象組成(當然也可以擴展為有多個目標對象,但我們現在只討論前者)的場合。當目標對象的狀態發生改變或做出某種行為時,正在觀察該目標對象的觀察者們將自動地、連鎖地作出相應的響應行為。

模式中具有的角色

  1. 抽象主題(Subject):它把所有觀察者對象的引用保存到一個聚集裏,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。
  2. 具體主題(ConcreteSubject):將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。
  3. 抽象觀察者(Observer):為所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
  4. 具體觀察者(ConcreteObserver):實現抽象觀察者角色所要求的更新接口,以便使本身的狀態與主題狀態協調。

舉例子:博客的例子就是一個觀察者模式,比如你關註一些作者的博客,當作者有博客發布時候,你就會收到一條該作者發布的博客的消息。

抽象主題:Blog 博客

具體主題:JiYFBlog 的博客

抽象觀察者:IObserver

具體的觀察者:Observer

觀察者模式類圖:

技術分享

觀察者模式C#代碼舉例

訂閱博客抽象類

 1 /*****************************************************
 2  * ProjectName:  _11DesignPattern_Observer
 3  * Description:
 4  * ClassName:    Blog
 5  * CLRVersion:   4.0.30319.18408
 6  * Author:       JiYF
7 * NameSpace: _11DesignPattern_Observer 8 * MachineName: JIYONGFEI 9 * CreateTime: 2017/5/23 17:08:10 10 * UpdatedTime: 2017/5/23 17:08:10 11 *****************************************************/ 12 using System; 13 using System.Collections.Generic; 14 using System.Linq; 15 using System.Text; 16 17 namespace _11DesignPattern_Observer 18 { 19 /// <summary> 20 /// 訂閱博客抽象類 21 /// </summary> 22 public abstract class Blog 23 { 24 /// <summary> 25 /// 保存訂閱者列表 26 /// </summary> 27 private List<IObserver> observers = new List<IObserver>(); 28 29 /// <summary> 30 /// 博主名 31 /// </summary> 32 public string BlogName { get; set; } 33 34 /// <summary> 35 /// 博客標題 36 /// </summary> 37 public string BlogTitle { get; set; } 38 39 /// <summary> 40 /// 博客信息 41 /// </summary> 42 public string BlogInfo { get; set; } 43 44 /// <summary> 45 /// 博客構造函數 46 /// </summary> 47 /// <param name="blogTitle">博客標題</param> 48 /// <param name="blogInfo">博客信息</param> 49 public Blog(string name,string blogTitle,string blogInfo) 50 { 51 this.BlogName = name; 52 this.BlogTitle = blogTitle; 53 this.BlogInfo = blogInfo; 54 } 55 56 /// <summary> 57 /// 添加一個訂閱者 58 /// </summary> 59 /// <param name="observer">具體的訂閱者對象</param> 60 public void AddObserver(IObserver observer) 61 { 62 if (observers.Contains(observer)) 63 { 64 return; 65 } 66 observers.Add(observer); 67 } 68 69 /// <summary> 70 /// 刪除一個訂閱者 71 /// </summary> 72 /// <param name="observer">具體的訂閱者對象</param> 73 public void RemoveObserver(IObserver observer) 74 { 75 if (observers.Contains(observer)) 76 { 77 observers.Remove(observer); 78 } 79 } 80 81 /// <summary> 82 /// 發布博客通知 83 /// </summary> 84 public void PublishBlog() 85 { 86 //遍歷通知每一個訂閱者 87 foreach (IObserver ob in observers) 88 { 89 if (ob != null) 90 { 91 ob.Receive(this); 92 } 93 } 94 } 95 96 } 97 }

具體的博客類

 1 /*****************************************************
 2  * ProjectName:  _11DesignPattern_Observer
 3  * Description:
 4  * ClassName:    JiYFBlog
 5  * CLRVersion:   4.0.30319.18408
 6  * Author:       JiYF
 7  * NameSpace:    _11DesignPattern_Observer
 8  * MachineName:  JIYONGFEI
 9  * CreateTime:   2017/5/23 17:21:23
10  * UpdatedTime:  2017/5/23 17:21:23
11 *****************************************************/
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 
17 namespace _11DesignPattern_Observer
18 {
19 
20     /// <summary>
21     /// 具體的訂閱博客類
22     /// </summary>
23     public class JiYFBlog :Blog
24     {
25         public JiYFBlog(string name,string blogTitile, string blogInfo)
26             : base(name,blogTitile,blogInfo)
27         {
28             
29         }
30     }
31 }

訂閱者接口類

 1 /*****************************************************
 2  * ProjectName:  _11DesignPattern_Observer
 3  * Description:
 4  * ClassName:    IObserver
 5  * CLRVersion:   4.0.30319.18408
 6  * Author:       JiYF
 7  * NameSpace:    _11DesignPattern_Observer
 8  * MachineName:  JIYONGFEI
 9  * CreateTime:   2017/5/23 17:09:28
10  * UpdatedTime:  2017/5/23 17:09:28
11 *****************************************************/
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 
17 namespace _11DesignPattern_Observer
18 {
19     /// <summary>
20     /// 訂閱者接口
21     /// </summary>
22     public interface IObserver
23     {
24 
25         void Receive(Blog blog);
26     }
27 }

具體的訂閱者類:

 1 /*****************************************************
 2  * ProjectName:  _11DesignPattern_Observer
 3  * Description:
 4  * ClassName:    Observer
 5  * CLRVersion:   4.0.30319.18408
 6  * Author:       JiYF
 7  * NameSpace:    _11DesignPattern_Observer
 8  * MachineName:  JIYONGFEI
 9  * CreateTime:   2017/5/23 17:23:36
10  * UpdatedTime:  2017/5/23 17:23:36
11 *****************************************************/
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 
17 namespace _11DesignPattern_Observer
18 {
19     /// <summary>
20     /// 具體的訂閱者類
21     /// </summary>
22     public class Observer :IObserver
23     {
24         /// <summary>
25         /// 訂閱者名字
26         /// </summary>
27         private string m_Name;
28         public string Name
29         {
30             get { return m_Name; }
31             set { m_Name = value; }
32         }
33 
34         /// <summary>
35         /// 訂閱者構造函數
36         /// </summary>
37         /// <param name="name">訂閱者名字</param>
38         public Observer(string name)
39         {
40             this.m_Name = name;
41         }
42 
43         /// <summary>
44         /// 訂閱者接受函數
45         /// </summary>
46         /// <param name="blog"></param>
47         public void Receive(Blog blog)
48         {
49             Console.WriteLine("訂閱者:\"{0}\"觀察到了:{1}發布的一篇博客,標題為:{2},內容為:{3}",Name,blog.BlogName,blog.BlogTitle,blog.BlogInfo);
50         }
51     }
52 }

測試代碼:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace _11DesignPattern_Observer
 7 {
 8     class Client
 9     {
10         static void Main(string[] args)
11         {
12             Console.WriteLine("--全部訂閱者--");
13             //創建一個JiYF的博客
14             Blog jiyfBlog = new JiYFBlog("JiYF笨小孩","醜小鴨","醜小鴨的故事");
15 
16             //創建訂閱者
17             Observer obsZhangsan = new Observer("張三");
18             Observer obsLiSi = new Observer("李四");
19             Observer obsWangwu = new Observer("王五"); 
20 
21             //添加對JiYF博客的訂閱者
22             jiyfBlog.AddObserver(obsZhangsan);
23             jiyfBlog.AddObserver(obsLiSi);
24             jiyfBlog.AddObserver(obsWangwu);
25 
26             //通知訂閱者
27             jiyfBlog.PublishBlog();
28 
29             Console.WriteLine("--移除訂閱者張三--");
30             jiyfBlog.RemoveObserver(obsZhangsan);
31             jiyfBlog.PublishBlog();
32             Console.ReadLine();
33         }
34     }
35 }

運行結果:

技術分享

通常在C#代碼中,觀察者模式一般采用委托來實現如下所示

委托實現觀察者模式

抽象博客類:

 1 /*****************************************************
 2  * ProjectName:  _11DesignPattern_ObserverDelegateTest
 3  * Description:
 4  * ClassName:    Blog
 5  * CLRVersion:   4.0.30319.42000
 6  * Author:       JiYF
 7  * NameSpace:    _11DesignPattern_ObserverDelegateTest
 8  * MachineName:  JIYF_PC
 9  * CreateTime:   2017/5/23 20:48:00
10  * UpdatedTime:  2017/5/23 20:48:00
11 *****************************************************/
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 
17 namespace _11DesignPattern_ObserverDelegateTest
18 {
19     /// <summary>
20     /// 委托充當訂閱者接口類
21     /// </summary>
22     /// <param name="sender"></param>
23     public delegate void NotifyEventHandler(object sender);
24 
25     /// <summary>
26     /// 訂閱博客基類
27     /// </summary>
28     public class Blog
29     {
30         public NotifyEventHandler NotifyEvent;
31         /// <summary>
32         /// 博主名
33         /// </summary>
34         public string BlogName { get; set; }
35 
36         /// <summary>
37         /// 博客標題
38         /// </summary>
39         public string BlogTitle { get; set; }
40 
41         /// <summary>
42         /// 博客信息
43         /// </summary>
44         public string BlogInfo { get; set; }
45 
46         /// <summary>
47         /// 博客構造函數
48         /// </summary>
49         /// <param name="blogTitle">博客標題</param>
50         /// <param name="blogInfo">博客信息</param>
51         public Blog(string name, string blogTitle, string blogInfo)
52         {
53             this.BlogName = name;
54             this.BlogTitle = blogTitle;
55             this.BlogInfo = blogInfo;
56         }
57 
58         /// <summary>
59         /// 綁定訂閱事件
60         /// </summary>
61         /// <param name="ob">訂閱者</param>
62         public void AddObserver(NotifyEventHandler observer)
63         {
64             NotifyEvent += observer;
65         }
66 
67         /// <summary>
68         /// 取消綁定訂閱
69         /// </summary>
70         /// <param name="observer"></param>
71         public void RemoteObserver(NotifyEventHandler observer)
72         {
73             NotifyEvent -= observer;
74         }
75 
76         /// <summary>
77         /// 發布博客通知
78         /// </summary>
79         public void PublishBlog()
80         {
81             if(NotifyEvent != null)
82             {
83                 NotifyEvent(this);
84             }
85         }
86     }
87 }

具體的博客類

 1 /*****************************************************
 2  * ProjectName:  _11DesignPattern_ObserverDelegateTest
 3  * Description:
 4  * ClassName:    JiYFBlog
 5  * CLRVersion:   4.0.30319.42000
 6  * Author:       JiYF
 7  * NameSpace:    _11DesignPattern_ObserverDelegateTest
 8  * MachineName:  JIYF_PC
 9  * CreateTime:   2017/5/23 20:55:58
10  * UpdatedTime:  2017/5/23 20:55:58
11 *****************************************************/
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 
17 namespace _11DesignPattern_ObserverDelegateTest
18 {
19     /// <summary>
20     /// 具體的訂閱博客類
21     /// </summary>
22     public class JiYFBlog : Blog
23     {
24         public JiYFBlog(string name, string blogTitile, string blogInfo)
25             : base(name, blogTitile, blogInfo)
26         {
27 
28         }
29     }
30 }

訂閱者類

 1 /*****************************************************
 2  * ProjectName:  _11DesignPattern_ObserverDelegateTest
 3  * Description:
 4  * ClassName:    Observer
 5  * CLRVersion:   4.0.30319.42000
 6  * Author:       JiYF
 7  * NameSpace:    _11DesignPattern_ObserverDelegateTest
 8  * MachineName:  JIYF_PC
 9  * CreateTime:   2017/5/23 20:56:50
10  * UpdatedTime:  2017/5/23 20:56:50
11 *****************************************************/
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 
17 namespace _11DesignPattern_ObserverDelegateTest
18 {
19     /// <summary>
20     /// 具體的訂閱者類
21     /// </summary>
22     public class Observer
23     {
24         /// <summary>
25         /// 訂閱者名字
26         /// </summary>
27         private string m_Name;
28         public string Name
29         {
30             get { return m_Name; }
31             set { m_Name = value; }
32         }
33 
34         /// <summary>
35         /// 訂閱者構造函數
36         /// </summary>
37         /// <param name="name">訂閱者名字</param>
38         public Observer(string name)
39         {
40             this.m_Name = name;
41         }
42 
43         /// <summary>
44         /// 訂閱者接受函數
45         /// </summary>
46         /// <param name="blog"></param>
47         public void Receive(object obj)
48         {
49             Blog blog = obj as Blog;
50             if (blog != null)
51             {
52                 Console.WriteLine("訂閱者:\"{0}\"觀察到了:{1}發布的一篇博客,標題為:{2},內容為:{3}", Name, blog.BlogName, blog.BlogTitle, blog.BlogInfo);
53             }
54          }
55     }
56 }

測試代碼

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace _11DesignPattern_ObserverDelegateTest
 7 {
 8     class Client
 9     {
10         static void Main(string[] args)
11         {
12             Console.WriteLine("--全部訂閱者--");
13             //創建一個JiYF的博客
14             Blog jiyfBlog = new Blog("JiYF笨小孩","醜小鴨","醜小鴨的故事");
15             
16             //創建訂閱者
17             Observer obsZhangsan    = new Observer("張三");
18             Observer obsLiSi        = new Observer("李四");
19             Observer obsWangwu      = new Observer("王五"); 
20 
21             //添加對JiYF博客的訂閱者
22             jiyfBlog.AddObserver(new NotifyEventHandler(obsZhangsan.Receive));
23             jiyfBlog.AddObserver(new NotifyEventHandler(obsLiSi.Receive));
24             jiyfBlog.AddObserver(new NotifyEventHandler(obsWangwu.Receive));
25 
26             ////通知訂閱者
27             jiyfBlog.PublishBlog();
28 
29             Console.WriteLine("---移除訂閱者張三--");
30             jiyfBlog.RemoteObserver(new NotifyEventHandler(obsZhangsan.Receive));
31             jiyfBlog.PublishBlog();
32             Console.ReadLine();
33         }
34     }
35 }

運行結果:

技術分享

源代碼工程文件下載

C#設計模式--觀察者模式(發布-訂閱模式)