观察者模式(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. Egret白鹭开发小游戏之自定义load加载界面

    刚接触不久就遇到困难------自定义loading.想和其他获取图片方式一样获取加载界面的图片,结果发现资源还没加载就需要图片,在网上百度了许多,都没有找到正确的方式,通过自己的摸索,终于,,,我成 ...

  2. mysql迁移mpp数据库Greenplum

    1. 场景描述 因兄弟项目中mysql有点扛不住了,要做sql优化,但是业务有点小复杂,优化起来有点麻烦(sql嵌套有点多),便想着用Mpp数据库Greenplum测试下,看性能和复杂度怎么样,趟趟水 ...

  3. TypeScript语法基础

    什么是TypeScript? TypeScript是微软开发的一门编程语言,它是JavaScript的超集,即它基于JavaScript,拓展了JavaScript的语法,遵循ECMAScript规范 ...

  4. 2014 北京区域赛 dp

    Matt has N friends. They are playing a game together. Each of Matt’s friends has a magic number. In ...

  5. 实现一个基于码云的Storage

    实现一个简单的基于码云(Gitee) 的 Storage Intro 上次在 asp.net core 从单机到集群 一文中提到存储还不支持分布式,并立了一个 flag 基于 github 或者 开源 ...

  6. Go pprof性能调优

    在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling 的库,这篇文章 ...

  7. IDEA 配置Springboot项目热部署

    实现的方式概述 注意以下的热部署方式在IDEA是默认没有打开自动编译的,手动编译需要快捷键(Ctrl+Shift+F9),自动编译的修改配置如下:(注意刷新不要太快,会有1-2秒延迟) File-Se ...

  8. JavaScript中的this到底是怎样的?

    this是困惑JavaScript开发者的一大‘毒瘤’,在开发过程中,但凡用到this的时候,我们都会很头疼,那么这个this在JavaScript中到底是怎么样的?身为一个前端coder,这是一个避 ...

  9. Servlet控制台输出乱码问题

    在如下图的配置页面: 在此行添加编码格式:

  10. python做傅里叶变换

    傅里叶变换(fft) 法国科学家傅里叶提出,任何一条周期曲线,无论多么跳跃或不规则,都能表示成一组光滑正弦曲线叠加之和.傅里叶变换即是把一条不规则的曲线拆解成一组光滑正弦曲线的过程. 傅里叶变换的目的 ...