观察者模式(Observer Pattern)
一、概述
在软件设计工作中会存在对象之间的依赖关系,当某一对象发生变化时,所有依赖它的对象都需要得到通知。如果设计的不好,很容易造成对象之间的耦合度太高,难以应对变化。使用观察者模式可以降低对象之间的依赖,以松耦合的方式实现这一目标。
二、观察者模式
观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。其结构图如下:

Subject知道它的所有观察者并提供了观察者注册和删除订阅的接口。
Observer为那些在目标发生改变时需获得通知的对象定义一个更新接口。
ConcreteSubject实现Subject接口,当改变状态时向依赖于它的ConcreteObserver发送通知。
ConcreteObserver实现Observer的更新接口,使得自身能根据ConcreteSubject状态的不同而做出相应的改变。
观察者模式分为推模式和拉模式两种。推模式是当有通知时,把依赖对象的信息以参数的形式传递给所有观察者,而拉模式通知方法本身并不带任何的参数,是由观察者自己到依赖对象那里取回相关信息。在推模式下,所有观察者都通过参数传递的方式得到依赖对象的全部信息,与依赖对象之间的耦合较低,但不能实现“按需所取”所需要信息的。而拉模式仅仅是通知观察者,至于要不要提取依赖对象的信息则是观察者自己的事情,这么一来就实现“按需所取”,但往往要在ConcreteObserver里保存一个ConcreteSubject的引用,与ConcreteSubject的耦合也加强了。
观察者模式的Subject一般需要提供观察者注册和删除订阅的接口,但在.NET中,往往可以利用事件和委托的特性来实现观察者模式,这是一种更为优雅的方案。
三、示例
我们现在利用事件实现观察者模式。我们设计一个信用卡消费的简单例子,在消费的同时需要对用户账户进行扣款,同时对用户进行短信提醒。
首先定义信用卡类,当消费金额变动时会触发Notify方法通知该对象的所有观察者。
public class CreditCard : EventArgs
{
private float _spendAmount;
public event EventHandler<CreditCard> SpendMoney; public float SpendAmount
{
get
{
return _spendAmount;
}
set
{
_spendAmount = value;
Notify();
}
} private void Notify()
{
if (SpendMoney != null)
{
SpendMoney(this, this);
}
}
}
接着定义Observer接口,并使用户帐户类和短信提醒类实现这个接口,其中这两个ConcreteObserver类的Update方法签名必须与CreditCard中的事件SendMoney一致,否则就无法注册到CreditCard。
public interface IObserver<T>
{
void Update(Object sender, T e);
} public class SMSNotify : IObserver<CreditCard>
{
public void Update(Object sender, CreditCard e)
{
Console.WriteLine("Sms notify.Spend {0}", e.SpendAmount);
}
} public class Account : IObserver<CreditCard>
{
private float _accountAmount; public Account(float accountAmount)
{
_accountAmount = accountAmount;
} public void Update(Object sender, CreditCard e)
{
_accountAmount += e.SpendAmount;
Console.WriteLine("Account amount is {0}", _accountAmount);
}
}
最后看一下客户端调用。
static void Main(string[] args)
{
CreditCard creditCard = new CreditCard();
SMSNotify sms = new SMSNotify();
Account account = new Account();
creditCard.SpendMoney += account.Update;
creditCard.SpendMoney += sms.Update;
creditCard.SpendAmount = ;
}
观察者模式(Observer Pattern)的更多相关文章
- 设计模式 - 观察者模式(Observer Pattern) 详细说明
观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 设计模式 - 观察者模式(Observer Pattern) 详细解释
观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- 设计模式-观察者模式(Observer Pattern)
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...
- jQuery中的观察者模式(Observer Pattern)
在jQuery中,on方法可以为元素绑定事件,trigger方法可以手动触发事件,围绕这2个方法,我们来体验jQuery中的观察者模式(Observer Pattern). ■ on方法绑定内置事件, ...
- 设计模式 - 观察者模式(Observer Pattern) Java内置 用法
观察者模式(Observer Pattern) Java内置 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26601659 ...
- 二十四种设计模式:观察者模式(Observer Pattern)
观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...
- 使用C# (.NET Core) 实现观察者模式 (Observer Pattern) 并介绍 delegate 和 event
观察者模式 这里面综合了几本书的资料. 需求 有这么个项目: 需求是这样的: 一个气象站, 有三个传感器(温度, 湿度, 气压), 有一个WeatherData对象, 它能从气象站获得这三个数据. 还 ...
- php观察者模式(observer pattern)
... <?php /* The observer pattern implements a one-too-many dependency between objects. The objec ...
- 设计模式系列之观察者模式(Observer Pattern)
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作 ...
随机推荐
- 通过lua栈了解lua与c的交互
lua是如何执行的 其中分析.执行部分都是c语言实现的. lua与c的关系 lua的虚拟机是用c语言实现的,换句话说一段lua指令最终在执行时都是当作c语言来执行的,lua的global表,函数调用栈 ...
- Tukey‘s test方法 异常值
如何计算异常值 异常值就是和其他样本数据有显著差异的值.这个词在统计学中经常用到,可以表示数据异常或测量错误.明白算异常值的方法,对于正确理解数据非常有用,而且会引出更精确的结论.以下介绍一个很简单的 ...
- 安卓中location.href或者location.reload 不起作用
链接:https://www.cnblogs.com/joshua317/p/6163471.html 在移动wap中,经常会使用window.location.href去跳转页面,这个方法在绝大多数 ...
- luogu P4342 [IOI1998]Polygon
IOI早期这么多dp? 题目要求断掉环上的一边,我们可以断环为链,开两倍数组 容易想到dp,设\(f_{i,j}\)为区间\([i,j]\)的最大值,然后就是个枚举断点的区间dp 不过可能会有负数出现 ...
- C - Least Crucial Node
题目链接:https://cn.vjudge.net/contest/247936#problem/C 具体大意:给你起点和中点,总点数,边数.求到终点的最小割点. 具体思路:可以用tarjan算法来 ...
- Django开发笔记二
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.xadmin添加主题.修改标题页脚和收起左侧菜单 # ...
- jQuery-contextMenu使用教程
jQuery-contextMenu使用教程 效果如下图所示.在[右击菜单]处右击,会出现下面的效果. 添加引用 <script src="jQuery-contextMenu-mas ...
- C++学习6-面向对象编程基础(运算符重载、类的派生与继承、命名空间)
运算符重载 重载的运算符是具有特殊名字的函数:它们的名字由关键字operator和其后要定义的运算符号共同组成.重载的运算符是遵循函数重载的选择原则,根据不同类型或不同参数来选择不同的重载运算符. 运 ...
- 【转】Python基础语法
[转]Python基础语法 学习一门编程语言,通常是学习该语言的以下几个部分的内容: 基础语法:如,变量的声明与调用.基本输出语句.代码块语法.注释等: 数据类型:通常都为 数字.字符串.布尔值.数组 ...
- The videobuf2 API【转】
转自:https://blog.csdn.net/paul_liao/article/details/8986999 The videobuf2 API Author:CJOK Contact:cjo ...