C++设计模式:观察者模式

发布时间 2023-06-05 19:52:58作者: 韓さん

观察者模式又叫做发布-订阅模式;
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动的更新自己。

有两大类(主题和观察者)一共四个角色
从上面我们可以看到,这里面包含了:
(1) 抽象主题/抽象被观察者(Subject)角色:将所有观察者对象保存在一个集合中,可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象
(2) 具体主题/具体被观察者(ConcreteSubject)角色:该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知
(3) 抽象观察者(Observer)角色:它定义了一个更新接口,使得在得到主题/被观察者更新时通知自己
(4) 具体观察者(ConcreteObserver)角色:实现抽象观察者定义的更新接口,以便在得到主题/被观察者更新时通知自己更新自身状态

其UML类图如下:

observer.cpp:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <list>
using namespace std;

class Observer
{
    public:
        virtual void update(){}
        virtual string getName() {return "";}
};

class Subject
{
    public:
        void enroll(Observer *observer);
        void detach(Observer *observer);
        void notify();
        ~Subject();
    
    private:
        list<Observer*> observers;
};


class ConcreteSubject: public Subject 
{
    public:
        string getSubjectState();
        void setSubjectState(const string &str);
    
    private:
        string subjectState;
};

class ConcreteObserver:public Observer
{
    public:
        ConcreteObserver(ConcreteSubject *subject, string name);
        void update();
        string getName();
    
    private:
        string name;
        string observerState;
        ConcreteSubject *subject;
};

void Subject::enroll(Observer *observer)
{
    observers.push_back(observer);
}

void Subject::detach(Observer *observer)
{
    observers.remove(observer);
}

void Subject::notify()
{
    list<Observer*>::iterator it = observers.begin();
    while(it != observers.end())
    {
        (*it)->update();
        it++;
    }
}

Subject::~Subject()
{
    printf("开始析构了\n");
    list<Observer*>::iterator it = observers.begin();
    while(it != observers.end())
    {
        printf("开始删除: ");
        cout<<(*it)->getName()<<endl;
        delete *it;
        it++;
    }
    observers.clear();
}

string ConcreteSubject::getSubjectState()
{
    return subjectState;
}

void ConcreteSubject::setSubjectState(const string &str)
{
    subjectState = str;
}

ConcreteObserver::ConcreteObserver(ConcreteSubject *subject, string name)
{
    this->subject = subject;
    this->name = name;
}

void ConcreteObserver::update()
{
    observerState = subject->getSubjectState();
    cout<<"发布者更新东西了!!!订阅者: "<<name<<" 状态: "<<observerState<<endl; 
}

string ConcreteObserver::getName()
{
    return name;
}

int main()
{
    ConcreteSubject *sub = new ConcreteSubject;
    sub->enroll(new ConcreteObserver(sub, "第一个粉丝"));
    sub->enroll(new ConcreteObserver(sub, "第二个粉丝"));
    sub->enroll(new ConcreteObserver(sub, "第三个粉丝"));

    sub->setSubjectState("刘亦菲");
    sub->notify();
    printf("<<------------------------------------->>\n");
    sub->enroll(new ConcreteObserver(sub, "王二麻子"));
    sub->setSubjectState("刘诗诗");
    sub->notify();

    cout<<endl;
    delete sub;
    return 0;
}