引言

在现实生活中,处处可见观察者模式,例如,微信中的订阅号,订阅博客和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)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. 【设计模式】观察者模式 Observer Pattern

    定义:观察者模式定义了对象之间的一对多依赖.当“主题”(Object)状态改变事,所有依赖它的“观察者”(Observer)都会受到通知并自动更新.主题支持观察者订阅和退订. 观察者模式提供了一种对象 ...

  8. 【UE4 设计模式】观察者模式 Observer Pattern

    概述 描述 定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新.观察者模式又叫做 发布-订阅(Publish/Subscribe)模式 模型-视图(M ...

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

    观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...

  10. 设计模式 - 观察者模式(Observer Pattern) 详细说明

    观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

随机推荐

  1. 获取properties配置

    1.      使用@Value @Value("${swagger.enable}") 使用Spring的PropertyPlaceholderConfigurer关联 @Val ...

  2. FFmpeg库简介

    1.FFmpeg基本组成 FFmpeg框架的基本组成包含AVFormat.AVCodec.AVFilter.AVDevice.AVUtils等模块库,如下图所示. libavformat:用于各种音视 ...

  3. python:find()函数,字符串查询

    #find函数 # b中有a的元素则打印a对应的元素坐标(索引),否则打印-1 a = "abcd" b = "d" print(a.find(b))

  4. 用Eclipse进行远程Debug代码

    在新的公司,由于项目很大,在本机运行会很慢,所以都是在本地开发,在远程虚拟机上运行.这样就让我痛苦了,我怎么在本地Eclipse上进行debug调试呢,但是在公司前辈的指导下让我知道了本地Eclips ...

  5. DAVINCI开发原理

    本文中约定: [host] 表示主机PC机Linux [target] 表示目标板Linux DAVINCI开发原理之一----ARM端开发环境的建立(DVEVM) 1. 对DAVINCI平台,TI在 ...

  6. Open MSDN document directly without Visual Studio

    "C:\Program Files (x86)\Microsoft Help Viewer\v2.2\HlpViewer.exe" /catalogName VisualStudi ...

  7. centos6.5 源码安装 mysql

    1.下载源码包 我的版本:mysql-5.6.4-m7.tar.gz 2.安装之前先卸载CentOS自带的MySQL [root@localhost ~]# yum remove mysql 3.编译 ...

  8. 【祥哥带你玩HoloLens开发】了解如何实现远程主机为HoloLens实时渲染

    今天有一个兄弟在群里讲到他们的项目模型比较大,单用HoloLens运行设备的性能无法满足需要,问道如何将渲染工作交给服务器来做,讲渲染结果传给HoloLens.正好刚刚看官方github的时候发现一个 ...

  9. Cocoapods 版本升级

    和往常一样使用 Cocoapods ,执行命令: $ pod install #输出信息 /System/Library/Frameworks/Ruby.framework/Versions/2.0/ ...

  10. Linux下Maven的安装与使用

    pache Maven,是一个软件(特别是Java软件)项目管理及自动构建工具,由Apache软件基金会所提供.基于项目对象模型(POM)概念,Maven利 用一个中央信息片断能管理一个项目的构建.报 ...