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 版权全部 ...
随机推荐
- **字符串格式化:%和.format
字符串格式化:%和.format .format在许多方面看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你可能会想下面的代码不会有什么问题: "hi there %s" ...
- MySQL 索引优化原则
一.索引优化原则 1.最左前缀匹配原则,联合索引,mysql会从做向右匹配直到遇到范围查询(>.<.between.like)就停止匹配,比如a = 1 and b = 2 and c & ...
- Spring Boot启动流程详解
注:本文转自http://zhaox.github.io/java/2016/03/22/spring-boot-start-flow 环境 本文基于Spring Boot版本1.3.3, 使用了sp ...
- atl控件发布打包<转>
http://www.cnblogs.com/gengaixue/archive/2010/08/13/1799112.html ActiveX打包与发布 在VS2005或VS2008安装后发现路径* ...
- mysqldump test
CREATE TABLE IF NOT EXISTS `runoob_tbl`( `runoob_id` INT UNSIGNED AUTO_INCREMENT, `runoob_title` VAR ...
- docker plugin test
docker build -t docker-volume-drbd . id=$(docker create docker-volume-drbd true) docker export $id - ...
- bash's parameter expansion
[bash's parameter expansion] #: find first from left, remove-left ##: find last from left, remove le ...
- 网页静态化解决方案:Freemarker生成简单html页面
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP.它不仅 ...
- 存储过程中使用事务和try catch
一.存储过程中使用事务的简单语法 在存储过程中使用事务时非常重要的,使用数据可以保持数据的关联完整性,在Sql server存储过程中使用事务也很简单,用一个例子来说明它的语法格式: 代码 : Cre ...
- 微信OAuth2.0网页授权php示例
1.配置授权回调页面域名,如 www.aaa.com 2.模拟公众号的第三方网页,fn_system.php <?php if(empty($_SESSION['user'])){ header ...