观察者模式 Publish/Subscribe

观察者模式


概述

观察者模式

观察者(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


使用情景

  • 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值