简介:

观察者模式,也称为订阅-发布模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖他的对象都得到通知并被自动更新。

主要由以下几个部分组成:

a.Subject目标对象。它具有以下特征:

一个目标可以被多个观察者订阅

提供订阅和取消订阅的方法

当目标对象状态发生变化时,通知所有订阅者。

把Subject独立出来是因为他提供了观察者模式中常见的三个特征,每个观察者模式都是这样,可以抽象出来。具体的单独逻辑可放在ConcreteSubject具体的目标实现对象中。

b.Observer定义观察者的接口。提供方法(一般为接口),当目标对象发生变化通知过来,做对应的响应操作。可以在该方法中调用Subject目标对象,以获取目标对象的数据。

c.ConcreteSubject具体的目标实现对象。可以维护具体对象的一些个性化属性,如目标状态等。

d.ConcreteObserver观察者的具体实现对象。提供处理目标对象变化的具体响应操作。

具体实例:

报社发行报纸,广大读者可以订报,也可以取消订报。报社维护订阅者的名单,一旦有新的报纸印刷出来,及时发布给广大读者。

Subject目标对象:提供观察者模式的基本功能

上面的例子中,广大读者都在观察同一个报社对象,这个报社对象就是被观察的目标。一般建议在目标接口名称后面加上Subject

/// <summary>
/// Subject目标对象
/// </summary>
public class NewsPaperSubject
{
/// <summary>
/// 维护有效订阅者的列表。
/// </summary>
protected List<ReaderObserver> observerList = new List<ReaderObserver>(); /// <summary>
/// 提供公共接口,供注册订阅者
/// </summary>
/// <param name="aObserver"></param>
public void Attach(ReaderObserver aObserver)
{
observerList.Add(aObserver);
} /// <summary>
/// 提供公共接口,供取消注册订阅者
/// </summary>
/// <param name="aObserver"></param>
public void Detach(ReaderObserver aObserver)
{
observerList.Remove(aObserver);
} /// <summary>
/// 目标对象发生变化时,通知所有订阅的观察者
/// </summary>
protected void NotifyAllObservers()
{
foreach (ReaderObserver observer in observerList)
{
observer.update(this);
}
}
}

上面的例子中,仅实现了报社的基本功能,并没有定义报社出版报纸等功能,是为了这个更通用。具体的逻辑放在ConcreteSubject中。

ConcreteSubject具体的目标实现对象:真正的模板对象,日报

日报,在原来基类上新增属性:报纸的出版日期。修改了出版日期,相当于重新出版了新报纸,此时需要通知所有读者。

 
/// <summary>
/// ConcreteSubject具体的目标实现对象 -日报
/// </summary>
public class DaliyNewsPaper : NewsPaperSubject
{
public string Date
{
get { return _date; }
set
{
_date = value;
//改了出版日期,相当于重新出版了新报纸,此时需要通知所有读者。
NotifyAllObservers();
}
}
private string _date;
}
Observer定义观察者的接口:观察者的接口或者抽象类。
一般建议在观察者接口后面跟Observer
接口更新方法,建议命名以Update。
观察者订阅好报纸以后,在家里等着收报纸即可,没有其他的功能需要实现。这里先抽象出观察者接口,然后再后续类中具体实现。
/// <summary>
/// Observer定义观察者的接口
/// </summary>
public abstract class ReaderObserver
{
/// <summary>
/// 目标对象发生变化通知过来,响应操作接口方法。
/// <param name="aSubject">推送过来的目标对象</param>
/// </summary>
public abstract void update(NewsPaperSubject aSubject);
}
ConcreteSubject具体的目标实现对象:真正的观察者,读者
/// <summary>
/// ConcreteObserver观察者的具体实现对象 -读者
/// </summary>
public class DailyNewsPaperReader : ReaderObserver
{
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _name; public override void update(NewsPaperSubject aSubject)
{
Console.WriteLine("{0}已经收到{1}的报纸", _name, (aSubject as DaliyNewsPaper).Date);
}
}
测试代码如下:
public class ObserverTest
{
public static void Main(string[] args)
{
//创建目标对象:报纸
DaliyNewsPaper newsPaper = new DaliyNewsPaper(); //创建观察者对象:张三
DailyNewsPaperReader observer1 = new DailyNewsPaperReader();
observer1.Name = "张三";
//张三订报纸
newsPaper.Attach(observer1); //创建观察者对象:李四
DailyNewsPaperReader observer2 = new DailyNewsPaperReader();
observer2.Name = "李四";
//李四订报纸
newsPaper.Attach(observer2); //2013-10-24报纸出版,张三、李四收到报纸
Console.WriteLine("2013-10-24报纸出版了!!!");
newsPaper.Date = "2013-10-24";
Console.WriteLine(); //李四取消订报
newsPaper.Detach(observer2); //2013-10-25报纸出版,张三收到报纸
Console.WriteLine("2013-10-25报纸出版了!!!");
newsPaper.Date = "2013-10-25"; Console.ReadLine();
}
}
补充分析:
1.观察者模式一般都是目标对象跟观察者一对多的关系,即一个目标有多个观察者。
对于观察者需要观察多个目标的情况下,可以修改观察者的UPDATE方法,根据传入参数决定是哪个目标的变化,或者干脆定义不同名字的UPDATE方法来对应不同的目标调用。
2.观察者模式的变例:区别对待观察者
比如说:某公司的请假制度为,请假半天以下的,通知下项目经理和项目组内成员即可,请假3天以下(含3天)的,还需要通知部门经理,请假3天以上的,还需要通知总经理。
实例中,请假对象是一个目标对象,项目经理、项目组成员、部门经理、总经理都是观察者。但是不同的是,并不是每次请假都需要通知上述所有人,需要根据请假的天数来决定通知的范围。
如果使用观察者模式?怎么处理?
参考代码如下:
protected void NotifyObservers()
{
foreach (ReaderObserver observer in observerList)
{
//不管请多少天,都需要通知项目经理和项目组成员
observer.getJob().equals("项目经理").Update(this);
observer.getJob().equals("项目组成员").Update(this); if (this.Day > 0.5)
observer.getJob().equals("部门经理").Update(this); if(this.Death >3)
observer.getJob().equals("总经理").Update(this);
}
}
此时具体目标对象需要重写抽象目标对象的通知方法,在方法内部根据目标的属性来决定被通知的观察者。
 
 

设计模式-观察者模式(Observer)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 设计模式--观察者模式Observer(对象行为型)

    一.观察者模式 观察者模式是在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新.观察者模式也被称之为:主题-观察者模式,发布-订阅模式,前者是一,后者是多. ...

  7. 大话设计模式--观察者模式 Observer -- C++ 实现实例

    大话设计模式--1.观察者模式: 定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有的 观察者对象,使他们能够自动更新自己. 使用场合: 当一 ...

  8. [工作中的设计模式]观察者模式observer

    一.模式解析 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 观察者模式又叫订阅发布模式, ...

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

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

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

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

随机推荐

  1. JConsole connection failed

    最近用jconsole本地连接eclipse失败 , 如下图 : 在eclipse.ini中添加如下代码即可 -Dcom.sun.management.jmxremote.port=9999-Dcom ...

  2. java多线程之从任务中获取返回值

    package wzh.test; import java.util.ArrayList; import java.util.concurrent.Callable; import java.util ...

  3. C#异步编程 z

    http://www.cnblogs.com/fangyz/p/5134018.html 从.NET4.5开始,用async和await关键字再加上Task.Run是一个非常不错的异步编程模型. 1. ...

  4. windows 修改hosts

    2222.111.1.1 ip 格式要正确,否则硬解会失败. 220.11.1.1

  5. crm 4 注释与上传附件权限

    文档注释权限及上传附件是与实体的”追加到”权限有关. 文档注释权限及上传附件是与核心记录中”注释”的”追加”权限有关. 追加及追加到的权限,我的理解是与本实体有关联的实体的权限,比如你引用了其它表的字 ...

  6. ZOJ 3042 City Selection II 【序】【离散化】【数学】

    题意: 输入数据n,m.n代表工厂的数量,m代表城市的数量. 接下来n+m行为工厂和城市的坐标. 规定如图所示方向刮风,工厂的air会污染风向地区的air. 注意,工厂和城市的坐标表示的是从x到x+1 ...

  7. [HDU 4417] Super Mario (树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 题目大意:给你n个数,下标为0到n-1,m个查询,问查询区间[l,r]之间小于等于x的数有多少个 ...

  8. ProGuard

    ProGuard的作用:  1.创建紧凑的代码文档是为了更快的网络传输,快速装载和更小的内存占用. 2.创建的程序和程序库很难使用反向工程. 3.所以它能删除来自源文件中的没有调用的代码 4.充分利用 ...

  9. Chapter Schema

    Chapter Schema Schema是XF的核心,每一个读写方法都有一个相关联的Schema.方法首先解析Schema,然后再根据Schema的配置的执行. 那Schema是什么呢?Schema ...

  10. php 分享两种给图片加水印的方法

    本文章向码农们介绍 php 给图片加水印的两种方法,感兴趣的码农可以参考一下本文章的源代码. 方法一:PHP最简单的加水印方法 <?php // http://www.manongjc.com ...