Featured image of post 观察者模式

观察者模式

介绍了观察者模式的实现

引言

观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。这种模式通常用于实现事件处理系统、发布-订阅模型等。

观察者模式

  • 试想这样一个场景,有一个超市,里面有很多员工,他们需要共同管理这个超市
    • 当员工入职的时候,员工就会与超市产生联系,订阅超市信息
    • 这个时候,一个员工提出超市售卖商品进行折扣售卖,被超市采纳了。此时超市的相关信息被更改了,这时候超市就要通知所有的员工,不再按照原来价格进行售卖,而是用折扣价进行售卖。
    • 过了几天后,又有个员工提出了另一种营销策略,被超市采纳,超市也要通知所有员工新的售卖策略

上述的情景就用到了观察者模式,超市是被观察的对象,员工就是观察者,当被观察的对象信息发生改变,就要告诉所有的观察者信息改变,观察者也能根据信息改变进行自己的处理。

源码实现

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
//有一个抽象的观察者,观察某一个行为,并针对这一行为有一个抽象的处理
//具体的观察者继承继承抽象的观察者,同时实现自己的具体的处理
//对于被观察的行为,行为的发起者有一个观察者列表,发起行为时,调用所有观察者的具体处理

#include <iostream>
#include <vector>

using namespace std;

class AbstractObserver {
public:
    virtual void DoProcess(int num) = 0;        //通知观察者对象,需要进行重写
    virtual void ChangeSubject(int data) = 0;
    virtual ~AbstractObserver() = default;
};

class AbstractSubject {
public:
    virtual ~AbstractSubject() = default;
    virtual void ChangeData(int) = 0;
    virtual void NotifyObservers() = 0;

    void AddObserver(AbstractObserver* observer) {observers.push_back(observer);}

    void RemoveObserver(const AbstractObserver* observer) {
        for (auto it = observers.begin(); it != observers.end(); ++it) {
            if (*it == observer) {
                observers.erase(it);
            }
        }
    }

protected:
    vector<AbstractObserver*> observers;
};

class Observer1 final : public AbstractObserver {
public:
    explicit Observer1(AbstractSubject* subject) : subject_(subject) {
        subject_->AddObserver(this);
    }
    void DoProcess(const int num) override {cout << "Observer1 : " << num << endl;}
    void ChangeSubject(const int data) override {subject_->ChangeData(data);}
private:
    AbstractSubject* subject_;
};

class Observer2 final : public AbstractObserver {
public:
    explicit Observer2(AbstractSubject* subject) : subject_(subject) {
        subject_->AddObserver(this);
    }
    void DoProcess(const int num) override {cout << "Observer2 : " << num << endl;}
    void ChangeSubject(const int data) override {subject_->ChangeData(data);}
private:
    AbstractSubject* subject_;
};

class Observer3 final : public AbstractObserver {
public:
    explicit Observer3(AbstractSubject* subject) : subject_(subject) {
        subject_->AddObserver(this);
    }
    void DoProcess(const int num) override {cout << "Observer3 : " << num << endl;}
    void ChangeSubject(const int data) override {subject_->ChangeData(data);}
private:
    AbstractSubject* subject_;
};

class Subject final : public AbstractSubject {
public:
    explicit Subject(const int data = 0) : data_(data){}
    void ChangeData(const int data) override {
        data_ = data;
        NotifyObservers();
    }

    void NotifyObservers() override {
        for (const auto & observer : observers) {
            observer -> DoProcess(data_);
        }
    }

private:
    int data_;
};

int main() {
    AbstractSubject* subject = new Subject();

    AbstractObserver* observer1 = new Observer1(subject);
    AbstractObserver* observer2 = new Observer2(subject);
    AbstractObserver* observer3 = new Observer3(subject);

    observer1 -> ChangeSubject(2);  //观察者1更改目标,所有观察者都应该显示更改后的目标

    cout << "-------------------------------" << endl;

    observer2 -> ChangeSubject(612);  //观察者2更改目标,所有观察者都应该显示更改后的目标

    subject -> RemoveObserver(observer1);   //删除1号观察者

    cout << "-------------------------------" << endl;

    observer3 -> ChangeSubject(100);  //观察者3更改目标,所有观察者都应该显示更改后的目标

    delete subject;
    delete observer1;
    delete observer2;
    delete observer3;
}

下面就来说明上面代码中每一个类的作用

  • AbstractObserver:抽象观察者类

    • 提供了修改被观察对象的纯虚函数
    • 提供了对被观察对象信息变化后进行处理的纯虚函数
  • Observer1,2,3:具体观察者类, 继承了抽象观察者类

    • 具有抽象被观察对象的指针,构造函数可以传入不同的具体被观察对象
    • 实现了基类的纯虚函数,实现更改被观察对象的信息,以及观察对象信息改变后自己要做的事情(DoProcess)。
  • AbstractSubject:抽象被观察对象类

    • 提供了观察者集合
    • 提供了增加观察者和删除观察者的函数(已经实现)
    • 提供了更改数据和通知观察者的纯虚函数
  • Subject:具体的被观察对象类,继承了抽象的被观察对象类

    • 重写更改数据的纯虚函数,并在调用通知函数
    • 重新通知函数,调用每一个观察者的DoProcess函数,并将被修改的数据传入进去

使用的时候,用抽象被观察对象类型指针接受一个具体的被观察对象指针,新建具体观察者的时候,传入这个指针(将被观察对象和观察者联系起来)。当一个观察者调用ChangeSubject时,其被观察对象会调用ChangeData函数更改信息,ChangeData函数里面还会调用NotifyObservers函数,在NotifyObservers函数里面,所有观察者会调用DoProcess应对被观察对象的数据变化。