观察者模式-对象行为模式

来源:互联网 发布:字中找字软件下载 编辑:程序博客网 时间:2024/05/17 04:04

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

动机:将一个系统分割成一系列相互协作的类有一个副作用:需要维护相关对象间的一致性。不希望为了维持一致性而使各类紧密耦合,这样会降低可重用性。

Observer模式中的关键对象是目标(subject)和观察者(observer.一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得到通知。作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标的状态同步。

这种交互也称为“发布-订阅”。目标是通知的发布者。它发出通知时并不需要知道谁是它的观察者。可以有任意数目的观察者订阅并接收通知。

适用性:

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

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

3当一个对象必须通知其它对象,而它又不能假定其它对象是谁。即不希望对象是紧密耦合的

结构:


 

参与者:

Subject(目标):

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

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

Observer(观察者):

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

ConcreteSubject(具体目标):

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

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

ConcreteObserver(具体观察者):

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

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

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

协作:

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

在得到一个具体目标的改变通知后,ConcreteObserver对象可向目标对象查询信息。ConcreteObserver使用这些信息以使它的状态与目标对象的状态一致。

如下图说明了一个目标对象和两个观察者之间的协作:

 

发出改变请求的Observer对象并不立即更新,而是将其推迟到它从目标得到一个通知之后。Notify不总是由目标对象调用。也可被一个观察者或其它对象调用。

效果:

1目标与观察者之间的抽象耦合。

2支持广播通信:可以广播给所有已向该目标对象登记的有关对象。

3意外的更新

实现:

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

2观察多个目标:一个观察者依赖于多个目标。

3谁触发更新。

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

B 由客户负责在适当的时候调用Notify

4 对已删除目标的悬挂引用:删除一个目标时不应遗留对该目标的悬挂引用

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

6避免特定于观察者的更新协议----/拉模型

推模型(push model):目标向观察者发生关于改变的详细信息,而不管它们是否需要

拉模型(pull model):目标除最小通知外什么也不送出,这之后由观察者显示向目标询问

7显示的指定感兴趣的改变

8封装复杂的更新语义:当目标和观察者间的依赖关系特别复杂时,使用ChangeManager来维护这些关系。目标是尽量减少观察者反应器目标的状态变化所需的工作量。

9结合目标类和观察者类

相关模式:

Mediator:通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。

SiglentonChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。


代码如下:

//观察者模式 #include <iostream>#include <list>#include <algorithm>using namespace std;class Subject;//抽象观察者 class Observer{public:Observer(string name, Subject* sub)  : _name(name), _sub(sub){}  virtual void Update() = 0;protected:    string _name;Subject* _sub; };//通知者接口class Subject{public://增加 virtual void Attach(Observer& observer){observers.push_back(&observer);}virtual void Detach(Observer& observer){observers.remove(&observer);}virtual void Notify(){//通知每一个观察者 for_each(observers.begin(), observers.end(), mem_fun(&Observer::Update));}//状态virtual string GetSubjectState(){return action;} virtual void SetSubjectState(string value){action = value;}protected:list<Observer*> observers;string action;}; //具体通知者class Boss : public Subject{}; //前台秘书类 class Secretary : public Subject{}; //看股票的同事class StockObserver : public Observer{public://设置通知者 StockObserver(string name, Subject* sub)    : Observer(name, sub){}void Update(){cout << _sub->GetSubjectState() << _name << "关闭股票行情,继续工作" << endl;}}; //看NBA的同事class NBAObserver : public Observer{public:NBAObserver(string name, Subject* sub)    : Observer(name, sub){}void Update(){cout << _sub->GetSubjectState() << _name << "关闭NBA直播,继续工作!" << endl;}}; int main(){//目标,通知者 Boss huhansan;//看股票的同事StockObserver tongshi1("魏关宅", &huhansan); //看NBA的同事NBAObserver tongshi2("易管查", &huhansan);huhansan.Attach(tongshi1);huhansan.Attach(tongshi2);//huhansan.Detach(tongshi1);huhansan.SetSubjectState("我胡汉三回来了!");huhansan.Notify();system("pause");return 0; }


0 0
原创粉丝点击