观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象,这个主题对象在状态发生变化时,会通知所有观察者。当一个对象改变需要同时改变其他对象,而且他不知道具体有多少对象需要改变的时候,应该考虑使用观察者模式。

观察者模式有四个角色:抽象主题、具体主题、抽象观察者、具体观察者。

ISubject接口(抽象目标):把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。含方法Notify,Register,UnRegister(名字可以自己任意取名)

Subject类(实体目标):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。实现ISubject接口,一般只有一个

IObservable接口(抽象观察者):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

Observer类(实体观察者):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。实现IObservable接口,一般有多个

观察者模式中的“注册--通知--注销”图示:
1. 观察者(Observer)将自己(Regiester)注册到被观察对象(Subject)中,被观察对象将观察者放在一个容器(Container)。Container一般为Ilist,Arraylist等数据结构,存放多个IObservable接口变量。
2.当被观察对象(Subject)发生变化时,容器(Container)中的所有观察者(Observer)都得到通知(Notify 方法),此时观察者会自动执行某些方法。
3.当观察者不想继续观察被观察者时,可以注销(UnRegiester方法)

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

缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

实现代码

抽象观察者(IObservable):

     /// <summary>
/// 只是为了把多个对象产生关系,方便保存和调用
/// 方法本身其实没用
/// </summary>
public interface IObserver
{
void Action();
}

实体观察者(Observer):

     public class Baby : IObserver
{
public void Action()
{
this.Cry();
} public void Cry()
{
Console.WriteLine("{0} Cry", this.GetType().Name);
}
}
     public class Brother : IObserver
{
public void Action()
{
this.Turn();
}
public void Turn()
{
Console.WriteLine("{0} Turn", this.GetType().Name);
}
}
     public class Chicken : IObserver
{
public void Action()
{
this.Woo();
}
public void Woo()
{
Console.WriteLine("{0} Woo", this.GetType().Name);
}
}
     public class Dog : IObserver
{
public void Action()
{
this.Wang();
}
public void Wang()
{
Console.WriteLine("{0} Wang", this.GetType().Name);
}
}
     public class Father : IObserver
{
public void Action()
{
this.Roar();
}
public void Roar()
{
Console.WriteLine("{0} Roar", this.GetType().Name);
}
}
     public class Mother : IObserver
{
public void Action()
{
this.Whisper();
}
public void Whisper()
{
Console.WriteLine("{0} Whisper", this.GetType().Name);
}
}
     public class Mouse : IObserver
{
public void Action()
{
this.Run();
}
public void Run()
{
Console.WriteLine("{0} Run", this.GetType().Name);
}
}
     public class Neighbor : IObserver
{
public void Action()
{
this.Awake();
}
public void Awake()
{
Console.WriteLine("{0} Awake", this.GetType().Name);
}
}
     public class Stealer : IObserver
{
public void Action()
{
this.Hide();
}
public void Hide()
{
Console.WriteLine("{0} Hide", this.GetType().Name);
}
}

实体目标(Subject):

     /// <summary>
/// 一只神奇的猫
///
/// 猫叫一声之后触发
/// baby cry
/// brother turn
/// dog wang
/// father roar
/// mother whisper
/// mouse run
/// neighbor awake
/// stealer hide
///
/// </summary>
public class Cat
{
public void Miao()
{
Console.WriteLine("{0} Miao.....", this.GetType().Name); new Mouse().Run();//依赖
new Chicken().Woo();
new Baby().Cry();
new Brother().Turn();
new Dog().Wang();
new Father().Roar();
new Mother().Whisper();
//new Mouse().Run();
new Neighbor().Awake();
//new Stealer().Hide();
}
//依赖太多,任何一个对象改动,都会导致Cat变化
//违背了单一职责,不仅自己miao 还要触发各种动作,不稳定
//加一个/减一个/调整顺序 Cat都得改 //Cat职责:1 Miao 2 触发一系列动作 这是需求
//实现上,其实多了一个,3 指定动作 //Cat不稳定--这一堆对象--甩锅--自己不写让别人传递
private List<IObserver> _ObserverList = new List<IObserver>();
public void AddObserver(IObserver observer)
{
this._ObserverList.Add(observer);
}
public void MiaoObserver()
{
Console.WriteLine("{0} MiaoObserver.....", this.GetType().Name);
if (this._ObserverList != null && this._ObserverList.Count > )
{
foreach (var item in this._ObserverList)
{
item.Action();
}
}
} public event Action MiaoHandler;
public void MiaoEvent()
{
Console.WriteLine("{0} MiaoEvent.....", this.GetType().Name);
if (this.MiaoHandler != null)
{
foreach (Action item in this.MiaoHandler.GetInvocationList())
{
item.Invoke();
}
}
} }

前端调用:

                 {
Console.WriteLine("***************Common******************");
Cat cat = new Cat();
cat.Miao();
}
{
Console.WriteLine("***************Observer******************");
Cat cat = new Cat();
cat.AddObserver(new Mouse());
cat.AddObserver(new Chicken());
cat.AddObserver(new Baby());
cat.AddObserver(new Brother());
cat.AddObserver(new Dog());
cat.AddObserver(new Father());
cat.AddObserver(new Mother());
cat.AddObserver(new Mouse());
cat.AddObserver(new Neighbor());
cat.AddObserver(new Stealer());
cat.MiaoObserver();
} {
Console.WriteLine("***************Observer******************");
Cat cat = new Cat();
cat.MiaoHandler += new Baby().Cry;
cat.MiaoHandler += new Brother().Turn;
cat.MiaoHandler += new Dog().Wang;
cat.MiaoHandler += new Stealer().Hide;
cat.MiaoHandler += new Neighbor().Awake;
cat.MiaoHandler += new Father().Roar;
cat.MiaoEvent();
}

交互的对象之间应尽量设计成松耦合的

松耦合设计可以让我们设计出这样的系统: 因为对象之间的相互依存减小了, 所以系统可以轻松处理变化

松耦合系统通常是基于消息的系统,此时客户端和远程服务并不知道对方是如何实现的。客户端和服务之间的通讯由消息的架构支配。只要消息符合协商的架构,则客户端或服务的实现就可以根据需要进行更改,而不必担心会破坏对方

当两个对象是松耦合的时候, 他们可以进行交互, 但是却几乎不了解对方.
观察者模式下的被观察者(Subject)和观察者(Observers)就是松耦合设计的对象. 这是因为:

    • 被观察者(Subject)只知道观察者实现了某个接口

    • 可以随时添加观察者

    • 添加新类型观察者的时候不需要修改被观察者

    • 可以复用观察者或者被观察者

    • 如果被观察者或观察者发生变化了, 那么这些变化不会影响到对方

使用委托的时候, 通常会有两个角色出现: 广播者(被观察者)和订阅者(观察者) [观察者模式]

广播者包含一个委托field, 广播者决定何时广播, 它通过调用委托进行广播.

订阅者就是方法的目标接收者.订阅者可以决定何时开始和结束监听, 是通过在广播者的委托上使用+=和-=操作符来实现的.

订阅者之间互相不了解, 不干扰.

event就是为上述模型所存在的, 它只把上述模型所必须的功能从委托里暴露出来. 它的主要目的就是防止订阅者之间相互干扰.

最简单声明event的方法就是在委托成员前面加上event关键字

本文参考文档:

https://www.runoob.com/design-pattern/observer-pattern.html

https://www.cnblogs.com/abcdwxc/archive/2007/09/19/898856.html

https://www.cnblogs.com/zhiyong-ITNote/p/10970067.html

https://mp.weixin.qq.com/s/XkfiFKPTbOy6kGGzfQOFpA

https://www.jb51.net/article/31665.htm

https://blog.csdn.net/u011966339/article/details/69388534

23种设计模式之观察者模式(Observer Pattern)的更多相关文章

  1. 二十四种设计模式:观察者模式(Observer Pattern)

    观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...

  2. 实践GoF的23种设计模式:观察者模式

    摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...

  3. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  4. 23种设计模式之观察者模式(Observer)

    观察者模式又称为发布—订阅模式.模型—视图模式.源-监听器模式或从属者(dependents)模式,是一种对象的行为型模式.它定义了对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相 ...

  5. 【Unity与23种设计模式】观察者模式(Observer)

    GoF中定义: "在对象之间定义一个一对多的连接方法,当一个对象变换状态时,其他关联的对象都会自动收到通知." 现实中,社交网络就是个例子. 以前的报社,每次出新刊的时候, 报刊便 ...

  6. [设计模式] 19 观察者模式 Observer Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...

  7. c#设计模式之观察者模式(Observer Pattern)

    场景出发 一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了 这个过程,如果用面向对象语言来描述,简单莫过于下: public class Cat { ...

  8. 设计模式之观察者模式(Observer pattern)

    最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下: 上课铃声响起,学生A/B/C/D进入教室:下课铃声响起,学生A/B/C/D离开教室. 要求使用设计模式的思想完成铃与学 ...

  9. 设计模式九: 观察者模式(Observer Pattern)

    简介 观察者属于行为型模式的一种, 又叫发布-订阅模式. 如果一个对象的状态发生改变,依赖他的对象都将发生变化, 那么这种情况就适合使用观察者模式. 它包含两个术语,主题(Subject),观察者(O ...

随机推荐

  1. unity之游戏特效

    一.运动轨迹 运动轨迹常常用于表现武器的挥舞效果,在提高速度感的同时又能让玩家看清楚招式动作,所以是常见的一种格斗特效. Unity中可以直接使用TrailRender来实现该效果. 二.运动模糊 运 ...

  2. urllib爬虫模块

    网络爬虫也称为网络蜘蛛.网络机器人,抓取网络的数据.其实就是用Python程序模仿人点击浏览器并访问网站,而且模仿的越逼真越好.一般爬取数据的目的主要是用来做数据分析,或者公司项目做数据测试,公司业务 ...

  3. 模板列传值到子窗体中,子窗体中多选gridview中checkbox保存数据多项到数据库中

    <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...

  4. Nginx总结(五)如何配置nginx和tomcat实现反向代理

    前面讲了如何配置Nginx虚拟主机,大家可以去这里看看nginx系列文章:https://www.cnblogs.com/zhangweizhong/category/1529997.html 今天要 ...

  5. 不修改的主席(HJT)树-HDU2665,POJ-2104;

    参考:优秀的B站视频:   和 https://blog.csdn.net/creatorx/article/details/75446472 感觉主席树这个思路是真的优秀,每次在前一次的线段树的基础 ...

  6. 【百度之星】【java大数+C++做法】hdu 6719 Strassen

    代码:递归搜索一下.java大数做法 import java.util.*; import java.math.*; import java.security.MessageDigest; publi ...

  7. D-query

    SPOJ - DQUERY 题意 求区间内出现一共有几种数字. 上次写了一个主席树,这次用一下莫队,莫队是离线询问的一种操作,将询问分块,如果在同一个块内就按照右端点排序,如果不在同一个块内就按照块的 ...

  8. Unsolved输入格式错误1022

    https://pintia.cn/problem-sets/994805342720868352/problems/994805480801550336

  9. Service:让客户端发现pod并与之通信

    5.1.Service介绍 5.1.1.Serice简介 5.1.1.1什么是Service service是k8s中的一个重要概念,主要是提供负载均衡和服务自动发现. Service 是由 kube ...

  10. MySQL连接方式小结

    1.   连接方式 1.1  方式1 /usr/local/mysql5./bin/mysql -p 此方法默认采用root@localhost用户登录, 1.2  方式2 /usr/local/my ...