观察者模式 Publish/Subscribe
2016-05-13 11:40
330 查看
观察者模式
概述
UML图
实现 c
观察者
被观察角色
测试
结果
note
使用情景
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依 赖于它的对象都得到通知并被自动更新。
面向对象设计的一个重要原则——单一职责原则。系统的每个对象应该 将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。这样在开发中也就带来了诸多的好处: 提供了重用性和维护性,也是进行重构的良好的基础。
因此几乎所有的设计模式都是基于这个基本的设计原则来的。
其中:
- 抽象目标角色(Subject): 目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。
- 抽象观察者角色(Observer): 为那些在目标发生改变时需要获得通知的对象定义一个更新接口. 抽象观察者角色主要由抽象类或者接口来实现。
- 具体目标角色(Concrete Subject): 将有关状态存入各个 Concrete Observer 对象。当它的状态发生改变时, 向它的各个观察者发出通知。
- 具体观察者角色(Concrete Observer): 存储有关状态,这些状态应与目标的状态保持一致。实现 Observer 的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向 Concrete Subject 对象的引用。
subject attach
subject attach
observer1 update
observer2 update
start both ob1 & ob2:
ob1: start ob2:start
subject detach
observer2 update
end ob2:
ob1: start ob2:end
╓ a.hpp ═
╙ a.cpp
╓ b.hpp ═
╙ b.cpp
当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
概述
UML图
实现 c
观察者
被观察角色
测试
结果
note
使用情景
观察者模式
概述
观察者(Observer)模式又名
发布-订阅(Publish/Subscribe)模式。GOF 给观察者模式如下定义:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依 赖于它的对象都得到通知并被自动更新。
面向对象设计的一个重要原则——单一职责原则。系统的每个对象应该 将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。这样在开发中也就带来了诸多的好处: 提供了重用性和维护性,也是进行重构的良好的基础。
因此几乎所有的设计模式都是基于这个基本的设计原则来的。
UML图
其中:
- 抽象目标角色(Subject): 目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。
- 抽象观察者角色(Observer): 为那些在目标发生改变时需要获得通知的对象定义一个更新接口. 抽象观察者角色主要由抽象类或者接口来实现。
- 具体目标角色(Concrete Subject): 将有关状态存入各个 Concrete Observer 对象。当它的状态发生改变时, 向它的各个观察者发出通知。
- 具体观察者角色(Concrete Observer): 存储有关状态,这些状态应与目标的状态保持一致。实现 Observer 的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向 Concrete Subject 对象的引用。
实现 (c++)
观察者
// observer.hpp #ifndef observer_hpp #define observer_hpp #include <string> #include "log.hpp" #include "subject.hpp" class subject; class observer { public: observer() {}; std::string state; virtual void update(subject& subject); }; class observer1 : public observer { public: observer1() {} void update(subject& subject); }; class observer2 : public observer { public: observer2() {} void update(subject& subject); }; #endif /* observer_hpp */
// observer.cpp #include "observer.hpp" void observer::update(subject& subject) { Log::i("observer update"); } void observer1::update(subject& subject) { this->state = subject.get_state(); Log::i("observer1 update"); } void observer2::update(subject& subject) { this->state = subject.get_state(); Log::i("observer2 update"); }
被观察角色
// subject.hpp #ifndef subject_hpp #define subject_hpp #include <vector> #include <string> #include "observer.hpp" class observer; class subject { public: void attach(observer* observer_instance); void detach(observer* observer_instance); void set_state(std::string state); std::string get_state(); void notify(); ~subject(); subject(); private: std::vector<observer*> _observers; std::string _state; }; class subject1 : public subject { public: subject1() {} }; class subject2 : public subject { public: subject2() {} }; #endif /* subject_hpp */
// subject.cpp #include "subject.hpp" subject::subject() { } subject::~subject() { } void subject::set_state(std::string state) { this->_state = state; } std::string subject::get_state() { return this->_state; } void subject::attach(observer* observer_instance) { Log::i("subject attach"); auto iter = find(_observers.begin(), _observers.end(), observer_instance); if (iter == _observers.end()) { this->_observers.push_back(observer_instance); } } void subject::detach(observer* observer_instance) { Log::i("subject detach"); auto iter = find(_observers.begin(), _observers.end(), observer_instance); if (iter != _observers.end()) { _observers.erase(iter); } } void subject::notify() { for (auto iter = _observers.begin(); iter != _observers.end(); ++iter) { (*(*iter)).update(*this); } }
测试
// main.cpp #include "subject.hpp" using std::cout; using std::endl; int main() { observer* ob1 = new observer1(); observer* ob2 = new observer2(); subject* sub1 = new subject1(); subject* sub2 = new subject2(); sub1->attach(ob1); sub1->attach(ob2); sub2->attach(ob1); sub1->set_state("start"); sub1->notify(); // 检查结果 cout << "start both ob1 & ob2: " << endl; cout << "ob1: " << ob1->state << "\tob2:" << ob2->state << endl; cout << endl; sub1->set_state("end"); sub1->detach(ob1); sub1->notify(); cout << "end ob2: " << endl; cout << "ob1: " << ob1->state << "\tob2:" << ob2->state << endl; cout << endl; return 0; }
结果
subject attachsubject attach
subject attach
observer1 update
observer2 update
start both ob1 & ob2:
ob1: start ob2:start
subject detach
observer2 update
end ob2:
ob1: start ob2:end
note
两个互相引用的类的实现问题╓ a.hpp ═
#include "b.hpp" class b;
╙ a.cpp
╓ b.hpp ═
#include "a.hpp" class a;
╙ b.cpp
使用情景
当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
相关文章推荐
- XAMPP升级PHP
- Qt之图形(绘制漂亮的圆弧)
- Qt之图形(绘制漂亮的圆弧)
- java复合语句与条件语句
- AllJoyn核心应用教程【第五章】:Base Services服务之Configuration
- Spring boot Common application properties
- C语言中#define用法总结
- 在异步提交Form数据时防止重复提交插件clockSubmit
- iscroll
- PHP中array_chunk()函数
- react-0.14.7
- Nginx源码分析 ——Nginx的进程模型
- iOS关于小数点的四舍五入
- hdu1890 Robotic Sort (splay+区间翻转单点更新)
- 网络协议
- 再谈二叉树:三种遍历六种实现
- 结合代码Diff做客户端测试
- 如何查看gtk版本 pkg使用
- X-Forwarded-For 负载均衡 7 层 HTTP 模式获取来访客户端真实 IP 的方法(IIS/Apache/Nginx/Tomcat)
- Excel中如何在两个工作表中查找重复数据