//---------------------------15/04/27----------------------------

//Observer 观察者模式----对象行为型模式

/*

1:意图:

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

2:别名:

依赖(Dependents),发布-订阅(Publish-Subscribe)

3:动机:

4:适用性:

1>当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这两者封装在独立的对象中以使它们可以各自独立

地改变和复用。

2>当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。

3>当一个对象必须通知其他对象,而它又不能假定其他对象是谁。

5:结构:

Subject:

observers-------------------------->Observer:

Attach(Observer)                    Update()

Detach(Observer)                        |

Notify()                                |

{ for all o in observers                |

{ o->Update()}                      |

}                                       |

|                                   |

|                               ConcreteObserver:

ConcreteSubject:<-------------------subject

GetState()                          Update()

{ return subjectState}              { observerState = subject->GetState()}

SetState()                          observerState

subjectState

6:参与者:

1>Subject:

1)目标知道它的观察者。可以有任意多个观察者观察同一目标。

2)提供注册和删除观察者对象的接口。

2>Observer:

为那些在目标发生改变时需获得通知的对象定义一个更新接口。

3>ConcreteSubject:

1)将有关状态存入各ConcreteObserver对象。

2)当它的状态发生改变时,向它的各个观察者发出通知。

4>ConcreteObserver:

1)维护一个指向ConcreteSubject对象的引用。

2)存储有关状态,这些状态应与目标的状态保持一致。

3)实现Observer的更新接口以使自身状态与目标的状态保持一致。

7:协作:

1>当ConcreteSubject发生任何可能导致其观察者与其本身状态不一致的改变时,它将通知它的各个观察者。

2>在得到一个具体目标的改变通知后,ConcreteObserver对象可向目标对象查询信息。ConcreteObserver

使用这些信息以使它的状态与目标对象的状态一致。

8:效果:

1>优点:

1)目标和观察者间的抽象耦合:

一个目标所知道的仅仅是它有一系列的观察者,每个都符合抽象的Observer类的简单接口。

目标不知道任何一个观察者属于哪个具体的类。这样的耦合关系时最小的。

2)支持广播通信:

不像通常的请求,目标发送的通知不需要指定它的接受者,通知被自动广播给所有已向该目标对象登记

的有关对象。

2>缺点:

意外的更新:

因为观察者并不知道其他观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害

的操作可能可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。

9:实现:

1>创建目标到其观察者之间的映射:

最简单的方式是在目标中存储观察者的指针,但是如果目标很多而观察者较少时,这样的存储代价太高,

所以可以用时间换空间,也就是使用一个关联查找机制(比如hash表)来维护目标到观察者的映射,这样

会增加访问观察者的开销。

2>观察多个目标:

如果要观察多个目标,必须扩展Update操作,加入一个参数,观察者知道应该检查哪一个目标。

3>谁触发更新:

1)目标:

由目标对象的状态设定操作在改变目标对象的状态后自动调用Notify,这样做的

优点是:客户不需要记住要在目标对象上调用Notify,

缺点是:多个连续的操作会产生多次连续的更新,造成较低的效率。

2)客户:

优点是:客户可以在做完一系列操作后再进行更新,效率更高,

缺点是:客户可能会忘记更新而造成错误。

4>对已删除的目标的悬挂引用:

当目标被删除时,观察者还保持着对目标的引用,因此会造成悬挂的情况,所以最好的做法是发送一个

通知,让观察者把指针设置为空。

5>在发出通知前确保目标的状态自身是一致的:

子类重定义一些操作时,可能造成先行通知(先调用基类的方法,这时已经通知过了),然后自己又改变了

状态。这样自身的状态前后是不一致的,所以避免这样的情况是模版方法:也就是在基类中使用一个non_virtual

的函数调用virtual函数,并在最后调用Notify,子类只能重新定义那个virtual函数,这样不管子类怎么改

最后都是会调用Notify的。

6>避免特定于观察者的更新协议:

1)目标在通知观察者的时候,传递了大量的信息(也就是Update的参数需要很多),这样使得观察者难以复用

这是因为Update参数的限制。

2)什么都信息都不传递,这样观察者需要付出大代价来知道什么东西改变了。

7>显式地指定感兴趣的改变:

可以让观察者注册自己感兴趣的事件,只有感兴趣的事件发生时,目标才会通知观察者。

8>封装复杂的更新语义:

依赖一个ChangeManager来维护目标和观察者之间的关系,它有三个责任:

1)它将一个目标映射到它的观察者并提供一个接口来维护这个映射,这样就不需要由目标来维护对其观察者

的引用。

2)它定义一个特定的更新策略。

3)根据一个目标的请求,它更新所有依赖于这个目标的观察者。

其实这就是一个中介者(Mediator)

10:代码示例:                                                                    */

//必须先声明是类才能声明一个List存放指针。

class Subject;

//观察者:

class Observer

{

public:

virtual ~Observer();

virtual void Update(Subject* theChangedSubject) =
;

protected:

Observer();

};

//目标:

class Subject

{

public:

virtual ~Subject();

virtual void Attach(Observer*);

virtual void Detach(Observer*);

virtual void Notify();

protected:

Subject();

private:

List<Observer*>* _observers;

};

//绑定观察者

void Subject::Attach(Observer* o)

{

_observers->Append(o);

}

//卸载观察者

void Subject::Detach(Observer* o)

{

_observers->Remove(o);

}

//通知所有观察者

void Subject::Notify()

{

ListIterator<Observer*> i(_observers);

for(i.First(); !i.IsDone(); i.Next())

{

i.CurrentItem()->Update(this);

}

}

//一个ConcreteSubject

class ClockTimer :
public Subject

{

public:

ClockTimer();

virtual int GetHour();

virtual int GetMinute();

virtual int GetSecond();

void Tick();

};

void ClockTimer::Tick()

{

//时间的变化。。。

Notify();

}

//ConcreteObserver

class DigitalClock:
public Widget, public Observer

{

public:

DigitalClock(ClockTimer*);

virtual ~DigitalClock();

virtual void Update(Subject*);

virtual void Draw();

private:

ClockTimer* _subject;

};

//注册自己

DigitalClock::DigitalClock(ClockTimer* s)

{

_subject = s;

_subject->Attach(this);

}

//卸载自己

DigitalClock::~DigitalClock()

{

_subject->Detach(this);

}

//Update操作,调用了Draw

void DigitalClock::Update(Subject* theChangedSubject)

{

if(theChangedSubject == _subject)

Draw();

}

//画出时间

void DigitalClock::Draw()

{

int hour = _subject->GetHour();

int minute = _subject->GetMinute();

//在窗口中根据时间画出数字钟

}

//另外一个钟

class AnalogClick :
public Widget, public Observer

{

public:

AnalogClick(ClockTimer*);

virtual void Update(Subject*);

virtual void Draw();

};

//使用:

ClockTimer* timer =
new ClockTimer;

AnalogClick* analogClick =
new AnalogClick(timer);

DigitalClock* digitalClock =
new DigitalClock(timer);

//一旦timer时间更新,这两个时钟都会被通知,然后调用自己取得时间,并画出来。

设计模式 笔记 观察者模式 Observer的更多相关文章

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

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

  2. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  3. 人人都会设计模式:观察者模式--Observer

    https://segmentfault.com/a/1190000012295887 观察者模式是抽像通知者和观察者,达到具体通知者跟具体观察者没有偶合.能达到不管是切换通知者,或者是切换观察者,都 ...

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

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

  5. [设计模式] 19 观察者模式 Observer Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...

  6. c#设计模式之观察者模式(Observer Pattern)

    场景出发 一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了 这个过程,如果用面向对象语言来描述,简单莫过于下: public class Cat { ...

  7. JAVA设计模式之观察者模式 - Observer

    有趣的事情发生时,可千万别错过了!有一个模式可以帮你的对象知悉现况,不会错过该对象感兴趣的事.对象甚至在运行时可决定是否要继续被通知.有了观察者,你将会消息灵通. 介绍 观察者模式的定义: 在对象之间 ...

  8. 设计模式之观察者模式(Observer pattern)

    最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下: 上课铃声响起,学生A/B/C/D进入教室:下课铃声响起,学生A/B/C/D离开教室. 要求使用设计模式的思想完成铃与学 ...

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

    观察者模式原理:当有新的消息产生时发送给观察者,和中介者模式的不同地方是中介者模式强调中介的作用以及中介双方的交互,观察者模式是主动调用观察者成员函数进行消息发送. 代码如下: #include &l ...

随机推荐

  1. 转:js小技巧 ,将彻底屏蔽鼠标右键,可用于Table ,取消选取、防止复制,IE地址栏前换成自己的图标

    1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table border oncontextmenu= ...

  2. c语言:复合文字

    复合文字的意义,相当于是在C语言中,为数组类型定义了一种类似于8之于int,'w'之于char一样的常量类型,所以从C99之后,可以在一些地方使用复合文字来代替数组使用. 复合文字的声明 (]){,, ...

  3. VS创建工程出错解决方案

    今天在用VS2010创建工程时出现错误:“ 此模板尝试加载组件程序集 “NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, Pu ...

  4. SDN 第二次上机作业

    SDN第二次上机作业 1.控制器floodlight所示可视化图形拓扑的截图,及主机拓扑连通性检测截图 拓扑 连通性 2.利用字符界面下发流表,使得'h1'和'h2' ping 不通 流表截图 连通性 ...

  5. Alpha冲刺报告(8/12)(麻瓜制造者)

    今日已完成 邓弘立: 完成了对主页UI控件的更新 符天愉: 没有完成留言模块,只是完成了留言的查询并且将留言多级回复格式化,同时和队友一起部署了商品发布的接口 江郑: 经过了这几天的编码,需求方面的数 ...

  6. python第二十九课——文件读写(读取数据操作)

    演示读取数据操作:path=r'a.txt' 1.打开文件f1=open(path,'r') 2.读取数据content1=f1.read(3)print(content1) content1=f1. ...

  7. BZOJ2502:清理雪道(有上下界最小流)

    Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时 ...

  8. 2298: [HAOI2011]problem a

    Description 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同的分数) 这句话的意思就等于是说第i个 ...

  9. POJ3801 Crazy Circuits

    嘟嘟嘟 上下界网络流之最小流. 建图不说啦,裸的. 在有附加源\(S\)和附加汇\(T\)的图上跑完后,删除和\(S, T\)相连的边.然后因为可能流多了,所以现在应该退流,于是我们从\(t\)到\( ...

  10. 【转】1.2 CDN的基本工作过程

    1.2  CDN的基本工作过程 使用CDN会极大地简化网站的系统维护工作量,网站维护人员只需将网站内容注入CDN的系统,通过CDN部署在各个物理位置的服务器进行全网分发,就可以实现跨运营商.跨地域的用 ...