一、概述
在软件设计工作中会存在对象之间的依赖关系,当某一对象发生变化时,所有依赖它的对象都需要得到通知。如果设计的不好,很容易造成对象之间的耦合度太高,难以应对变化。使用观察者模式可以降低对象之间的依赖,以松耦合的方式实现这一目标。

二、观察者模式
观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。其结构图如下:

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)的更多相关文章

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

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

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

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

  3. 设计模式 - 观察者模式(Observer Pattern) 详细解释

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

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

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

  5. jQuery中的观察者模式(Observer Pattern)

    在jQuery中,on方法可以为元素绑定事件,trigger方法可以手动触发事件,围绕这2个方法,我们来体验jQuery中的观察者模式(Observer Pattern). ■ on方法绑定内置事件, ...

  6. 设计模式 - 观察者模式(Observer Pattern) Java内置 用法

    观察者模式(Observer Pattern) Java内置 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26601659 ...

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

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

  8. 使用C# (.NET Core) 实现观察者模式 (Observer Pattern) 并介绍 delegate 和 event

    观察者模式 这里面综合了几本书的资料. 需求 有这么个项目: 需求是这样的: 一个气象站, 有三个传感器(温度, 湿度, 气压), 有一个WeatherData对象, 它能从气象站获得这三个数据. 还 ...

  9. php观察者模式(observer pattern)

    ... <?php /* The observer pattern implements a one-too-many dependency between objects. The objec ...

  10. 设计模式系列之观察者模式(Observer Pattern)

    意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作 ...

随机推荐

  1. javascript 缓动返回顶部案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. codeforces - 432D Prefixes and Suffixes (next数组)

    http://codeforces.com/problemset/problem/432/D 转自:https://blog.csdn.net/tc_to_top/article/details/38 ...

  3. 5. SprigBoot自动配置原理

      配置文件到底能写什么?怎么写? 都可以在SpringBoot的官方文档中找到: 配置文件能配置的属性参照   1.自动配置原理: 1).SpringBoot启动的时候加载主配置类,开启了自动配置功 ...

  4. android HttpClient将数据提交到服务器

    1.HttpClient 使用方式 public static String loginByClientGet(String username,String password) { try { //打 ...

  5. Varish 缓存

    varish 缓存 2013年06月17日,Varnish Cache 3.0.4 发布,为目前最新版本. varish是以内存作为共享容器的:内存的大小决定了它的缓存容量.相对于主要以硬盘为存储的s ...

  6. UE4的AI学习(1)——基本概念

    AI学习当中,不学习行为树基本概念就不能明白具体实例中的操作意义,但是没有经过具体实例实验,又觉得基本概念抽象难以理解.建议先泛读(1)(2)后再对具体的细节进行死磕,能较深的理解行为树的具体概念.第 ...

  7. c#将前端传来的Json解析成对象

    描述:因工作中需要将C#中的Json字符串转换为对象,对此记录下. 解决办法: 1.前端传过来的Json字符串,OrderAppModuleJson即前端传递到后端的Json字符串 string st ...

  8. [转]bus error与segment error

    在c程序中,经常会遇到段错误(segment error)和总线错误(bus error),这两种问题出现的原因可能如下 段错误: 对一个NULL指针解引用. 访问程序进程以外的内存空间. 实际上,第 ...

  9. SSM框架报错分析(一)——There is no getter for property named 'XXX' in 'class java.lang.String'

    一.发现问题 <select id="queryStudentByNum" resultType="student" parameterType=&quo ...

  10. Java InputStream 、 InputStreamReader和BufferedReader

    https://blog.csdn.net/zgljl2012/article/details/47267609 在Java中,上述三个类经常用于处理数据流,下面介绍一下三个类的不同之处以及各自的用法 ...