您的位置:首页 > 其它

观察者模式 Publish/Subscribe

2016-05-13 11:40 330 查看
观察者模式
概述
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 attach

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

note

两个互相引用的类的实现问题

╓ a.hpp ═
#include "b.hpp" class b;


╙ a.cpp

╓ b.hpp ═
#include "a.hpp" class a;


╙ b.cpp

使用情景

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

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

当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: