c#设计模式系列:观察者模式(Observer Pattern)
引言
在现实生活中,处处可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用。在这一章将分享我对观察者模式的理解,废话不多说了,直接进入今天的主题。
观察者模式的介绍
2.1 观察者模式的定义
从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户。从中,我们就可以得出观察者模式的定义。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为。
2.2 观察者模式的结构图
可以看出,在观察者模式的结构图有以下角色:
- 抽象主题角色(Subject):抽象主题把所有观察者对象的引用保存在一个列表中,并提供增加和删除观察者对象的操作,抽象主题角色又叫做抽象被观察者角色,一般由抽象类或接口实现。
- 抽象观察者角色(Observer):为所有具体观察者定义一个接口,在得到主题通知时更新自己,一般由抽象类或接口实现。
- 具体主题角色(ConcreteSubject):实现抽象主题接口,具体主题角色又叫做具体被观察者角色。
- 具体观察者角色(ConcreteObserver):实现抽象观察者角色所要求的接口,以便使自身状态与主题的状态相协调。
2.3观察者模式的实现
下面我们已抖音为例,当你刷抖音时候,看到一个很不错的小视频,就关注了这个作者,以后作者每次更新视频的时候,系统都会给关注他的粉丝推送新的消息,下面是我写的第一版实现代码:
/// <summary>
/// 作者
/// </summary>
public class OAuth
{
private List<Fans> list = new List<Fans>();
public string name { get; set; } /// <summary>
/// 新增一个粉丝
/// </summary>
/// <param name="add"></param>
public void Add(Fans add)
{
list.Add(add);
}
/// <summary>
/// 减少一个粉丝
/// </summary>
/// <param name="remove"></param>
public void Remove(Fans remove)
{
list.Remove(remove);
}
public void Nofify()
{
foreach (Fans item in list)
{
item.Update();
}
}
}
/// <summary>
/// 粉丝
/// </summary>
public class Fans
{ private string name;
private OAuth sub;
public Fans(string name, OAuth sub)
{
this.name = name;
this.sub = sub;
}
public void Update()
{
Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看",name,sub.name);
}
} /// <summary>
/// 客户端
/// </summary>
class Program
{
static void Main(string[] args)
{ OAuth oauth = new OAuth();
oauth.name = "小炒肉";
Fans a = new Fans("青椒",oauth);
Fans b = new Fans("胡萝卜",oauth);
oauth.Add(a);
oauth.Add(b); oauth.Nofify(); Console.ReadLine();
}
}
//结果显示
你好:青椒,小炒肉发布了新的作品,点击查看
你好:胡萝卜,小炒肉发布了新的作品,点击查看
看到这种代码我们首先想到的是 违反了面向对象的开发-封闭原则,其次是依赖倒转原则,类与类之间不应该相互依赖,而应该依赖与抽象,好了,我们得重新修改了,10分钟后第二版出来了
public abstract class Observer
{
protected string name;
protected Subject sub;
public Observer(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void Update();
} public class Person : Observer
{
public Person(string name, Subject sub) : base(name, sub) { } public override void Update()
{
Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看", name, sub.name);
}
}
public abstract class Subject
{
public string name { get; set; }
public abstract void Add(Observer ob);
public abstract void Remove(Observer ob);
public abstract void Notify();
}
public class Green : Subject
{
private List<Observer> list = new List<Observer>();
public override void Add(Observer ob)
{
list.Add(ob);
}
public override void Notify()
{
foreach (var item in list)
{
item.Update();
}
}
public override void Remove(Observer ob)
{
list.Remove(ob);
}
}
/// <summary>
/// 客户端
/// </summary>
class Program
{
static void Main(string[] args)
{
Subject ob = new Green();
ob.name = "小炒肉";
Observer a = new Person("青椒", ob);
Observer b = new Person("胡萝卜", ob);
ob.Add(a);
ob.Add(b);
ob.Notify();
Console.ReadLine();
}
}
///结果
你好:青椒,小炒肉发布了新的作品,点击查看
你好:胡萝卜,小炒肉发布了新的作品,点击查看
现在已经依赖接口编程,但是“抽象通知者”还是依赖 抽象观察者,也就是说,万一没有了抽象观察者这样的接口,我这通知的功能就完成不了,下面我们引入委托解耦实现通知者和观察者
public class Person
{
protected string name;
protected Subject sub;
public Person(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public void UpdateTP()
{
Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看", name, sub.name);
}
}
public delegate void EventHandler();
public interface Subject
{
string name { get; set; }
void Notify();
}
public class Green : Subject
{ public event EventHandler Update;
public string name { get; set; } public void Notify()
{
Update();
}
}
/// <summary>
/// 客户端
/// </summary>
class Program
{
static void Main(string[] args)
{
Green hand = new Green();
hand.name = "小王";
Person per = new Person("青椒",hand);
Person Ge = new Person("小炒肉", hand);
hand.Update += new EventHandler(per.UpdateTP);
hand.Update += new EventHandler(Ge.UpdateTP); hand.Notify(); Console.ReadLine();
}
}
总结
在C#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。
好了在次复习下,观察者模式的定义,观察者模式定义了一种一对多的关系,让多个观察者对象可以同时监听某一个主题对象,这个主题对象在发送状态改变时,会通知所有观察者对象,时它们能够自动更新自己
c#设计模式系列:观察者模式(Observer Pattern)的更多相关文章
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 二十四种设计模式:观察者模式(Observer Pattern)
观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...
- [设计模式] 19 观察者模式 Observer Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...
- c#设计模式之观察者模式(Observer Pattern)
场景出发 一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了 这个过程,如果用面向对象语言来描述,简单莫过于下: public class Cat { ...
- 设计模式之观察者模式(Observer pattern)
最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下: 上课铃声响起,学生A/B/C/D进入教室:下课铃声响起,学生A/B/C/D离开教室. 要求使用设计模式的思想完成铃与学 ...
- 设计模式九: 观察者模式(Observer Pattern)
简介 观察者属于行为型模式的一种, 又叫发布-订阅模式. 如果一个对象的状态发生改变,依赖他的对象都将发生变化, 那么这种情况就适合使用观察者模式. 它包含两个术语,主题(Subject),观察者(O ...
- 【设计模式】观察者模式 Observer Pattern
定义:观察者模式定义了对象之间的一对多依赖.当“主题”(Object)状态改变事,所有依赖它的“观察者”(Observer)都会受到通知并自动更新.主题支持观察者订阅和退订. 观察者模式提供了一种对象 ...
- 【UE4 设计模式】观察者模式 Observer Pattern
概述 描述 定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新.观察者模式又叫做 发布-订阅(Publish/Subscribe)模式 模型-视图(M ...
- 设计模式-观察者模式(Observer Pattern)
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...
- 设计模式 - 观察者模式(Observer Pattern) 详细说明
观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
随机推荐
- leetcode495
public class Solution { public int FindPoisonedDuration(int[] timeSeries, int duration) { ) { ; } ) ...
- 分环境部署SpringBoot日志logback-spring.xml
springboot按照profile进行打印日志 log4j logback slf4j区别? 首先谈到日志,我们可能听过log4j logback slf4j这三个名词,那么它们之间的关系是怎么样 ...
- c# typeof 与 Type.GetType 使用与效率对比
static void ReflectionTest() {//测试两种反射的效率问题 //Type.GetType()只能在同一个程序集中使用,typeof则可以跨程序集(assembly) //通 ...
- PHP - 脚本退出(包括异常退出),执行指定代码
之前做聊天室的时候有那么个需求就是当用户异常断线的时候就应该清除她的在线状态.因为当时对于flush不够了解,尝试了各种办法,好像都没办法在我们开发机上面执行相应的代码.后来知道是flush的原因.我 ...
- iOS多线程编程之NSOperation和NSOperationQueue的使用
前一篇 <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是 ...
- Spring DI的配置使用
1.1.1 依赖和依赖注入Spring IOC容器的依赖有两层含义:Bean依赖容器和容器注入Bean的依赖资源:a.Bean依赖容器:也就是说Bean要依赖于容器,这里的依赖是指容器负责创建Bean ...
- Reducing File Size
[Reducing File Size] 1.Unity strips out unused assets. The amount of assets in your project folder d ...
- sql解决主键冲突
在数据插入的时候,假设主键对应的值已经存在,则插入失败!这就是主键冲突.当主键存在冲突(duplicate key)的时候,可以选择性的进行处理,即忽略.更新或者替换. 1.忽略 insert ign ...
- nodemon 的坑
1. 我的系统是ubuntu18.04.2 的 在使用过程中不知道什么为题 nodemon 运行的项目不在前台打印了项目, 我监听的端口 9302 一直在运行, 前台看不到 我想停止掉用 ps -ef ...
- 小程序本地资源无法通过 css 获取
background-image:可以使用网络图片,或者 base64,或者使用<image/>标签