观察者模式
2016-04-12 22:59
330 查看
观察者模式简单实现
UNL类图:观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
观察者模式角色:
● Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。
● ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
● Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。
● ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。
观察者模式优缺点:
1.主要优点
(1) 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
(2) 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
(3) 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
(4) 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。
2.主要缺点
(1) 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
(2) 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
(3) 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
观察者模式适用场景:
(1) 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。
(2) 一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁。
(3) 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
#pragma once #ifndef _OBSERVER_H_ #define _OBSERVER_H_ #define SAFE_DELETE(p) <span style="white-space:pre"> </span>\ if(nullptr!=(p))<span style="white-space:pre"> </span>\ { \ delete (p); \ (p)=nullptr; \ } #include <string> #include <list> using namespace std; //由于观察者与主题间互相引用,前向引用声明不能调用函数 所以定义分开最好分开写 class Subject; //抽象观察者 class Observer { public: /*观察者可以维持一个抽象主题指针 此处未使用,因为他们只在Notify会产生交互,此时调用Update时 可以得到主题改变后的状态。 */ ~Observer(); virtual void Update(Subject*) = 0; protected: Observer(); private: }; //具体观察者A class ConcreteObserverA : public Observer { public: ConcreteObserverA(); ~ConcreteObserverA(); virtual void Update(Subject*); protected: private: string m_state; }; //具体观察者B class ConcreteObserverB : public Observer { public: ConcreteObserverB(); ~ConcreteObserverB(); virtual void Update(Subject*); protected: private: string m_state; }; //------------------------------------------------ //抽象主题 class Subject { public: ~Subject(); virtual void Notify(); virtual void Attach(Observer*); virtual void Detach(Observer*); virtual string GetState(); virtual void SetState(string state); protected: Subject(); private: string m_state; //维持一个抽象观察者的链表 list<Observer*> m_lst; }; //具体主题 class ConcreteSubjectA : public Subject { public: ConcreteSubjectA(); ~ConcreteSubjectA(); protected: private: }; class ConcreteSubjectB : public Subject { public: ConcreteSubjectB(); ~ConcreteSubjectB(); protected: private: }; #endif
#include "Observer.h" #include <iostream> #include <algorithm> using namespace std; Observer::Observer() {} Observer::~Observer() {} ConcreteObserverA::ConcreteObserverA() {} ConcreteObserverA::~ConcreteObserverA() {} void ConcreteObserverA::Update(Subject* pSubject) { this->m_state = pSubject->GetState(); cout << "The ConcreteObserverA is " << m_state << std::endl; } ConcreteObserverB::ConcreteObserverB() {} ConcreteObserverB::~ConcreteObserverB() {} void ConcreteObserverB::Update(Subject* pSubject) { this->m_state = pSubject->GetState(); cout << "The ConcreteObserverB is " << m_state << std::endl; } Subject::Subject() {} Subject::~Subject() {} void Subject::Attach(Observer* pObserver) { this->m_lst.push_back(pObserver); cout << "Attach an Observer\n"; } void Subject::Detach(Observer* pObserver) { list<Observer*>::iterator iter; iter = find(m_lst.begin(), m_lst.end(), pObserver); if (iter != m_lst.end()) { m_lst.erase(iter); } cout << "Detach an Observer\n"; } void Subject::Notify() { list<Observer*>::iterator iter = this->m_lst.begin(); for (; iter != m_lst.end(); iter++) { (*iter)->Update(this); } } string Subject::GetState() { return this->m_state; } void Subject::SetState(string state) { this->m_state = state; } ConcreteSubjectA::ConcreteSubjectA() {} ConcreteSubjectA::~ConcreteSubjectA() {} ConcreteSubjectB::ConcreteSubjectB() {} ConcreteSubjectB::~ConcreteSubjectB() {}
#include "Observer.h" #include <iostream> using namespace std; int main() { Observer* p1 = new ConcreteObserverA(); Observer* p2 = new ConcreteObserverB(); Observer* p3 = new ConcreteObserverA(); Subject* pSubject = new ConcreteSubjectA(); pSubject->Attach(p1); pSubject->Attach(p2); pSubject->Attach(p3); pSubject->SetState("old"); //实际上的Notify可以对应不同的行为 pSubject->Notify(); cout << "-------------------------------------" << endl; pSubject->SetState("new"); pSubject->Detach(p3); pSubject->Notify(); SAFE_DELETE(p1); SAFE_DELETE(p2); SAFE_DELETE(p3); SAFE_DELETE(pSubject); return 0; }
相关文章推荐
- EJB、RMI、XMLRPC、Hessian、Thrift 、Protobuf
- json-c代码示例
- 操作系统面试题总结
- struts2标签在jsp不显示问题(不经过action跳转)
- C语言中未初始化变量的值
- mysql 数据库字段与关键字冲突,报语法错误
- Codeforces Round #306 (Div. 2) B.Preparing Olympiad (位运算)
- 编写一个程序,这个程序把一个整数数组中的每个元素用逗号连接成一个字符串,例如,根 据内容为[1][2][3]的数组形成内容为"1,2,3"的字符串。
- 编写 三个类 ticket,sealWindow,ticketSealCenter,代表票信息,售票窗口,售票中心, 售票中心分配一定数量的票(多个窗口实现多线程售票)
- 理解 Linux 网络栈(1):Linux 网络协议栈简单总结
- Android自动化测试之Monkeyrunner使用方法及实例
- 【每周一文】Field-aware Factorization Machine(2014)
- android去除标题栏
- POJ-1256 next_permutation函数应用
- Android Studio导入第三方jar包
- 策略模式的孪生兄弟——对状态模式的深度复习总结
- oracle压缩表空间
- CSUST 第九届校赛H-最小差值
- 京东2016实习题目-选举游戏-小东和其他小朋友正在玩一个关于选举的游戏。选举是通过投票的方式进行的,得票最多的人将获胜。
- vs2010 出错:error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏