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

Subject知道它的所有观察者并提供了观察者注册和删除订阅的接口。
Observer为那些在目标发生改变时需获得通知的对象定义一个更新接口。
ConcreteSubject实现Subject接口,当改变状态时向依赖于它的ConcreteObserver发送通知。
ConcreteObserver实现Observer的更新接口,使得自身能根据ConcreteSubject状态的不同而做出相应的改变。
观察者模式分为推模式和拉模式两种。推模式是当有通知时,把依赖对象的信息以参数的形式传递给所有观察者,而拉模式通知方法本身并不带任何的参数,是由观察者自己到依赖对象那里取回相关信息。在推模式下,所有观察者都通过参数传递的方式得到依赖对象的全部信息,与依赖对象之间的耦合较低,但不能实现“按需所取”所需要信息的。而拉模式仅仅是通知观察者,至于要不要提取依赖对象的信息则是观察者自己的事情,这么一来就实现“按需所取”,但往往要在ConcreteObserver里保存一个ConcreteSubject的引用,与ConcreteSubject的耦合也加强了。
观察者模式的Subject一般需要提供观察者注册和删除订阅的接口,但在.NET中,往往可以利用事件和委托的特性来实现观察者模式,这是一种更为优雅的方案。
三、示例
我们现在利用事件实现观察者模式。我们设计一个信用卡消费的简单例子,在消费的同时需要对用户账户进行扣款,同时对用户进行短信提醒。
首先定义信用卡类,当消费金额变动时会触发Notify方法通知该对象的所有观察者。

 1     public class CreditCard : EventArgs
2 {
3 private float _spendAmount;
4 public event EventHandler<CreditCard> SpendMoney;
5
6 public float SpendAmount
7 {
8 get
9 {
10 return _spendAmount;
11 }
12 set
13 {
14 _spendAmount = value;
15 Notify();
16 }
17 }
18
19 private void Notify()
20 {
21 if (SpendMoney != null)
22 {
23 SpendMoney(this, this);
24 }
25 }
26 }

接着定义Observer接口,并使用户帐户类和短信提醒类实现这个接口,其中这两个ConcreteObserver类的Update方法签名必须与CreditCard中的事件SendMoney一致,否则就无法注册到CreditCard。

 1    public interface IObserver<T>
2 {
3 void Update(Object sender, T e);
4 }
5
6 public class SMSNotify : IObserver<CreditCard>
7 {
8 public void Update(Object sender, CreditCard e)
9 {
10 Console.WriteLine("Sms notify.Spend {0}", e.SpendAmount);
11 }
12 }
13
14 public class Account : IObserver<CreditCard>
15 {
16 private float _accountAmount;
17
18 public Account(float accountAmount)
19 {
20 _accountAmount = accountAmount;
21 }
22
23 public void Update(Object sender, CreditCard e)
24 {
25 _accountAmount += e.SpendAmount;
26 Console.WriteLine("Account amount is {0}", _accountAmount);
27 }
28 }

最后看一下客户端调用。

1     static void Main(string[] args)
2 {
3 CreditCard creditCard = new CreditCard();
4 SMSNotify sms = new SMSNotify();
5 Account account = new Account(1000);
6 creditCard.SpendMoney += account.Update;
7 creditCard.SpendMoney += sms.Update;
8 creditCard.SpendAmount = 200;
9 }
 
 

C#设计模式——观察者模式(Observer Pattern)的更多相关文章

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

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

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

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

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

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

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

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

  5. C#设计模式——观察者模式(Observer Pattern)1

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

  6. 23种设计模式--观察者模式-Observer Pattern

    一.观察者模式的介绍      观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...

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

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

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

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

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

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

随机推荐

  1. Codeforces Round #381 (Div. 1) B. Alyona and a tree dfs序 二分 前缀和

    B. Alyona and a tree 题目连接: http://codeforces.com/contest/739/problem/B Description Alyona has a tree ...

  2. webpack处理非模块化的几方法

    webpack处理非模块化文件有几方法,主要分为外链和webpack打包二种情况: 一.使用CDN外部链接的方法 官网文档External: https://webpack.github.io/doc ...

  3. 网页JS获取当前地理位置(省市区)

    眼看2014又要过去了,翻翻今年的文章好像没有写几篇,忙真的或许已经不能成为借口了,在忙时间还是有的,就像海绵里的水挤挤总会有滴.真真的原因是没有学习过什么新的技术,工作过程中遇到的问题也不是非常难并 ...

  4. 【转】关于TCP和UDP协议消息保护边界的介绍

    在 socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有一一成对的 socket,因此,发送端为了将多个发往接收端的包, ...

  5. Hadoop 2.7.1 使用minicluster进行单元测试

    目的是要跑通这个单元测试:hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestClose.java 这个Java文件比较简单: /** * Lic ...

  6. 将十六进制的颜色字符串转为UIColor

    扩展UIColor,将十六进制的颜色字符串转成UIColor对象. extension UIColor { static func colorWithHexString(hex:String) -&g ...

  7. 同时大量连接导致的DDOS攻击,导致收发器宕机,用户大面积超时掉线

    前段时间一个客户改成电信网通自动路由后(当然和这个没有关系,但是客户一般没有分析能力,会多想),用户经常大面积掉线,用户才180多个,在线最多也才120多,十分苦恼,原先帮其维护的技术人员,只是远程诊 ...

  8. Reset Entity-Framework Migrations

    You need to delete the state: Delete the migrations folder in your project Delete the __MigrationHis ...

  9. Windows 8.1 Preview 开发资源汇总

    Microsoft Build 2013开发者大会已经结束,从Session安排上看主要以Windows 8.1为主.我相信大家有已经或多或少的体验过Windows 8.1 Preview了,关于操作 ...

  10. CreateProcessAsUser,C#写的windows服务弹框提示消息或者启动子进程

    服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分.我们可以把服务想像成一种特殊的应用程序,它随系统的“开启-关闭”而“开始-停止”其工作内容,在这期间无需任何 ...