热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#设计模式观察者模式(发布订阅模式)

0.C#设计模式--简单工厂模式1.C#设计模式--工厂方法模式2.C#设计模式--抽象工厂模式3.C#设计模式--单例模式4.C#设计模式--建造者模式5.C#设计模式--原型模

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     /// 
20     /// 订阅博客抽象类
21     /// 
22     public abstract class Blog
23     {
24         /// 
25         /// 保存订阅者列表
26         /// 
27         private List observers = new List();
28 
29         /// 
30         /// 博主名
31         /// 
32         public string BlogName { get; set; }
33 
34         /// 
35         /// 博客标题
36         /// 
37         public string BlogTitle { get; set; } 
38 
39         /// 
40         /// 博客信息
41         /// 
42         public string BlogInfo { get; set; }
43 
44         /// 
45         /// 博客构造函数
46         /// 
47         /// 博客标题
48         /// 博客信息
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         /// 
57         /// 添加一个订阅者
58         /// 
59         /// 具体的订阅者对象
60         public void AddObserver(IObserver observer)
61         {
62             if (observers.Contains(observer))
63             {
64                 return;
65             }
66             observers.Add(observer);
67         }
68 
69         /// 
70         /// 删除一个订阅者
71         /// 
72         /// 具体的订阅者对象
73         public void RemoveObserver(IObserver observer)
74         {
75             if (observers.Contains(observer))
76             {
77                 observers.Remove(observer);
78             }
79         }
80 
81         /// 
82         /// 发布博客通知
83         /// 
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     /// 
21     /// 具体的订阅博客类
22     /// 
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     /// 
20     /// 订阅者接口
21     /// 
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     /// 
20     /// 具体的订阅者类
21     /// 
22     public class Observer :IObserver
23     {
24         /// 
25         /// 订阅者名字
26         /// 
27         private string m_Name;
28         public string Name
29         {
30             get { return m_Name; }
31             set { m_Name = value; }
32         }
33 
34         /// 
35         /// 订阅者构造函数
36         /// 
37         /// 订阅者名字
38         public Observer(string name)
39         {
40             this.m_Name = name;
41         }
42 
43         /// 
44         /// 订阅者接受函数
45         /// 
46         /// 
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     /// 
20     /// 委托充当订阅者接口类
21     /// 
22     /// 
23     public delegate void NotifyEventHandler(object sender);
24 
25     /// 
26     /// 订阅博客基类
27     /// 
28     public class Blog
29     {
30         public NotifyEventHandler NotifyEvent;
31         /// 
32         /// 博主名
33         /// 
34         public string BlogName { get; set; }
35 
36         /// 
37         /// 博客标题
38         /// 
39         public string BlogTitle { get; set; }
40 
41         /// 
42         /// 博客信息
43         /// 
44         public string BlogInfo { get; set; }
45 
46         /// 
47         /// 博客构造函数
48         /// 
49         /// 博客标题
50         /// 博客信息
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         /// 
59         /// 绑定订阅事件
60         /// 
61         /// 订阅者
62         public void AddObserver(NotifyEventHandler observer)
63         {
64             NotifyEvent += observer;
65         }
66 
67         /// 
68         /// 取消绑定订阅
69         /// 
70         /// 
71         public void RemoteObserver(NotifyEventHandler observer)
72         {
73             NotifyEvent -= observer;
74         }
75 
76         /// 
77         /// 发布博客通知
78         /// 
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     /// 
20     /// 具体的订阅博客类
21     /// 
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     /// 
20     /// 具体的订阅者类
21     /// 
22     public class Observer
23     {
24         /// 
25         /// 订阅者名字
26         /// 
27         private string m_Name;
28         public string Name
29         {
30             get { return m_Name; }
31             set { m_Name = value; }
32         }
33 
34         /// 
35         /// 订阅者构造函数
36         /// 
37         /// 订阅者名字
38         public Observer(string name)
39         {
40             this.m_Name = name;
41         }
42 
43         /// 
44         /// 订阅者接受函数
45         /// 
46         /// 
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#设计模式--观察者模式(发布-订阅模式)


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
author-avatar
求道金林
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有