麻花痒 发表于 2024-10-1 19:42:23

用C++实现观察者模式的几种变体

观察者模式的标准定义

定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当这个主题对象的状态发生改变时,会关照所有观察者对象,使它们可以或许主动更新自己的状态。
观察者模式的标准结构图

https://i-blog.csdnimg.cn/direct/1bcdffb213ae48cc9f715eaf9442e264.png#pic_center
观察者模式的标准实现

Subject(抽象主题)

Subject.h
#pragma once

#include <list>
#include <string>

class Observer;

class Subject
{
public:
        virtual ~Subject();

        virtual void addObserver(Observer* obsv);

        virtual void removeOvserver(Observer* obsv);

        virtual void notify();

private:
        std::list<Observer *> mObserverList;

};


Subject.cpp
#include "Subject.h"

#include "Observer.h"

Subject::~Subject()
{
        if (!mObserverList.empty())
        {
                mObserverList.clear();
        }
}

void Subject::addObserver(Observer* obsv)
{
        if (nullptr == obsv)
                return;
        bool bExist = false;
        std::list<Observer*>::const_iterator iter = mObserverList.begin();
        for (; iter != mObserverList.end(); ++iter)
        {
                Observer* const curObsv = iter.operator*();
                //*iter == obsv;
                if (curObsv == obsv)
                {
                        bExist = true;
                        break;
                }
        }

        if (bExist)
                return;
        mObserverList.push_back(obsv);
}

void Subject::removeOvserver(Observer* obsv)
{
        if (mObserverList.empty() || (nullptr == obsv))
                return;
        bool bExist = false;
        std::list<Observer*>::const_iterator iter = mObserverList.begin();
        for (; iter != mObserverList.end(); ++iter)
        {
                Observer* const curObsv = *iter;
                if (curObsv == obsv)
                {
                        bExist = true;
                        break;
                }
        }

        if (bExist)
                mObserverList.remove(obsv);
}

void Subject::notify()
{
        std::list<Observer*>::const_iterator iter;
        for (iter = mObserverList.begin(); iter != mObserverList.end(); ++iter)
        {
                Observer* const curObsv = *iter;
                curObsv->update();
        }
}
这里先说两个概念:原语函数、钩子函数
原语函数,即纯虚函数,意思就是必须在子类中重定义的函数;
钩子函数,即虚函数,意思是可以在子类中重定义的函数。
ConcreteSubject(具体主题)

ConcreteSubject.h
#pragma once
#include "Subject.h"
class ConcreteSubjectA :
    public Subject
{
public:
    void setState(bool b);
    bool getState() const;

    void changedState();

private:
    bool mSendToA = false;
    bool mSendToB = false;
};


ConcreteSubject.cpp
#include "ConcreteSubjectA.h"
#include <iostream>

void ConcreteSubjectA::setState(bool b)
{
        mSendToA = mSendToB = b;
        changedState();
}

bool ConcreteSubjectA::getState() const
{
        return (mSendToA && mSendToB);
}

void ConcreteSubjectA::changedState()
{
        std::cout << "刘亦菲来啦~" << std::endl;

        if (getState())
        {
                notify();
        }
}

Observer(抽象观察者)

Observer.h
#pragma once

class string;

class Observer
{
public:
        Observer();
        virtual ~Observer();

        virtual void update() = 0;

};
Observer.cpp
#include "Observer.h"

Observer::Observer()
{
}

Observer::~Observer()
{
}
ConcreteObserverA(具体观察者A)

ConcreteObserverA.h
#pragma once
#include "Observer.h"
class ConcreteObserverA :
    public Observer
{
public:
    ConcreteObserverA();
    ~ConcreteObserverA();

    virtual void update() override;

};

ConcreteObserver.cpp
#include "ConcreteObserverA.h"
#include <iostream>

ConcreteObserverA::ConcreteObserverA()
{
}

ConcreteObserverA::~ConcreteObserverA()
{
}

void ConcreteObserverA::update()
{
        std::cout << "我要上报给领导!" << std::endl;
}
ConcreteObserverB(具体观察者B)

ConcreteObserverB.h
#pragma once
#include "Observer.h"

class ConcreteSubjectA;

class ConcreteObserverB :
    public Observer
{
public:
    ConcreteObserverB();
    virtual ~ConcreteObserverB();

    virtual void update() override;

};
ConcreteObserverB.cpp
#include "ConcreteObserverB.h"

#include "ConcreteSubjectA.h"

#include <iostream>

ConcreteObserverB::ConcreteObserverB()
{
}

ConcreteObserverB::~ConcreteObserverB()
{

}

void ConcreteObserverB::update()
{
        std::cout << "我要通知其他人!" << std::endl;
}
主程序简单调用

#include "ConcreteObserverA.h"
#include "ConcreteSubjectA.h"
#include "ConcreteObserverB.h"

#include <iostream>

int main()
{
    // Standard version
    ConcreteObserverA* obsvA = new ConcreteObserverA();
    ConcreteObserverB* obsvB = new ConcreteObserverB();
    ConcreteSubjectA* subA = new ConcreteSubjectA();
    subA->addObserver(obsvA);
    subA->addObserver(obsvB);
    subA->setState(true);
    subA->removeOvserver(obsvB);
    subA->removeOvserver(obsvA);

    return EXIT_SUCCESS;
}
实在到这里,可以结束了;但是,好像又远远不敷。哪里不敷呢?
你难道不以为这两个观察者A、B有点太轻信于主题A了吗?不管谁给它们发消息,它们都相信 ,如许容易上当上当呀——说是刘亦菲来了,实在是刘姥姥来啦~。
观察者A、B也很委屈,腹诽道:我也不知道是谁给我的消息,我只知道,有消息,我就得做出反应;哪里还管得了你的、他的。
这还不简单…
观察者变身一

Observer.h
#pragma once

#include "Subject.h"

class Observer_SecondVer // 响应固定主题
{
public:
        Observer_SecondVer();
        Observer_SecondVer(Subject* subject);
        virtual ~Observer_SecondVer();

        virtual void update(Subject* subject = nullptr) = 0;

protected:
        Subject* mSubject = nullptr;

};
ConcreteObserverA.h
#pragma once
#include "Observer.h"

class ConcreteObserverA_SecondVer : public Observer_SecondVer
{
public:
    ConcreteObserverA_SecondVer();
    ConcreteObserverA_SecondVer(Subject* subject);
    ~ConcreteObserverA_SecondVer();

    virtual void update(Subject* subject = nullptr) override;

    void doSomething();
};
ConcreteObserverA.cpp
#include "ConcreteObserverA.h"
#include <iostream>

ConcreteObserverA_SecondVer::ConcreteObserverA_SecondVer()
{
}

ConcreteObserverA_SecondVer::ConcreteObserverA_SecondVer(Subject* subject) : Observer_SecondVer(subject)
{
}

ConcreteObserverA_SecondVer::~ConcreteObserverA_SecondVer()
{
}

void ConcreteObserverA_SecondVer::update(Subject* subject)
{
        if (subject && subject == mSubject)
        {
                doSomething();
        }
}

void ConcreteObserverA_SecondVer::doSomething()
{
        std::cout << "通知老板!" << std::endl;
}
ConcreteObserverB.h
#pragma once
#include "Observer.h"

class ConcreteSubjectA;

class ConcreteObserverB_SecondVer : public Observer_SecondVer
{
public:
    ConcreteObserverB_SecondVer();
    ConcreteObserverB_SecondVer(ConcreteSubjectA* subject);
    ~ConcreteObserverB_SecondVer();

    virtual void update(Subject* subject = nullptr) override;

    void doSomething();
};
ConcreteObserverB.cpp
#include "ConcreteObserverB.h"

#include "ConcreteSubjectA.h"

#include <iostream>

ConcreteObserverB_SecondVer::ConcreteObserverB_SecondVer()
{
}

ConcreteObserverB_SecondVer::ConcreteObserverB_SecondVer(ConcreteSubjectA* subject) : Observer_SecondVer(subject)
{
}

ConcreteObserverB_SecondVer::~ConcreteObserverB_SecondVer()
{
}

void ConcreteObserverB_SecondVer::update(Subject* subject)
{
        if (subject && subject == mSubject)
        {
                doSomething();
        }
}

void ConcreteObserverB_SecondVer::doSomething()
{
        std::cout << "通知其他人!" << std::endl;
}

怎么样?以后,只要观察者A、B认定了主题A的消息,都进行相应,是不是就没那么容易上当上当了。
突然,观察者A又有点其他的想法,弱弱地问道:“那个~我不想只看刘亦菲,只要是美女,能不能都给我发消息呀?”
啊~ 你这~
于是乎…
主题变身一/二 + 观察者变身二

Subject.h
#pragma once

#include <list>
#include <string>

class Observer;
class Observer_SecondVer;
class Observer_ThirdVer;

class Subject
{
public:
        virtual ~Subject();

        virtual void addObserver(Observer* obsv);

        virtual void removeOvserver(Observer* obsv);

        virtual void notify();

        virtual void addObserver(Observer_SecondVer* obsv);

        virtual void removeOvserver(Observer_SecondVer* obsv);

        virtual void notify_SecondVer();

        virtual void addObserver(Observer_ThirdVer* obsv);

        virtual void removeOvserver(Observer_ThirdVer* obsv);

        virtual void notify_ThirdVer();

private:
        std::list<Observer *> mObserverList;
        std::list<Observer_SecondVer*> mObserverList_SecondVer;
        std::list<Observer_ThirdVer*> mObserverList_ThirdVer;

};

Subject.cpp
void Subject::notify_SecondVer()
{
        std::list<Observer_SecondVer*>::const_iterator iter;
        for (iter = mObserverList_SecondVer.begin(); iter != mObserverList_SecondVer.end(); ++iter)
        {
                Observer_SecondVer* const curObsv = *iter;
                curObsv->update(this);
        }
}

void Subject::notify_ThirdVer()
{
        std::list<Observer_ThirdVer*>::const_iterator iter;
        for (iter = mObserverList_ThirdVer.begin(); iter != mObserverList_ThirdVer.end(); ++iter)
        {
                Observer_ThirdVer* const curObsv = *iter;
                curObsv->update(this, std::string("有美女!"));
        }
}
ConcreteSubjectA.h
#pragma once
#include "Subject.h"
class ConcreteSubjectA :
    public Subject
{
public:
    void setState(bool b);
    bool getState() const;

    void setStateA(bool b);
    bool getStateA() const;

    void setStateB(bool b);
    bool getStateB() const;

    void changedState();

private:
    bool mSendToA = false;
    bool mSendToB = false;
};

ConcreteSubjectA.cpp
#include "ConcreteSubjectA.h"
#include <iostream>

void ConcreteSubjectA::setState(bool b)
{
        mSendToA = mSendToB = b;
        changedState();
}

bool ConcreteSubjectA::getState() const
{
        return (mSendToA && mSendToB);
}

void ConcreteSubjectA::setStateA(bool b)
{
        std::cout << "美女来啦~" << std::endl;
        mSendToA = b;
        changedState();
}

bool ConcreteSubjectA::getStateA() const
{
        return mSendToA;
}

void ConcreteSubjectA::setStateB(bool b)
{
        std::cout << "刘亦菲来啦~" << std::endl;
        mSendToB = b;
        changedState();
}

bool ConcreteSubjectA::getStateB() const
{
        return mSendToB;
}

void ConcreteSubjectA::changedState()
{
        if (getStateA())
        {
                notify_SecondVer();
        }
        else if (getStateB())
        {
                notify_ThirdVer();
        }
        else if (getState())
        {
                notify();
                notify_SecondVer();
                notify_ThirdVer();
        }
        else
        {
                notify();
        }
}

Observer.h
#pragma once

#include "Subject.h"

class string;

class Observer_ThirdVer // 响应固定主题 + 固定消息
{
public:
        virtual ~Observer_ThirdVer() {}

        virtual void update(Subject* subject, const std::string& info) = 0;

};
ConcreteObserverA.h
#pragma once
#include "Observer.h"

class ConcreteObserverA_ThirdVer : public Observer_ThirdVer
{
public:
    ConcreteObserverA_ThirdVer() {}
    ConcreteObserverA_ThirdVer(Subject* subject);
    virtual ~ConcreteObserverA_ThirdVer();

    virtual void update(Subject* subject, const std::string& info) override;

protected:
    Subject* mSubject = nullptr;

};
ConcreteObserverA.cpp
#include "ConcreteObserverA.h"
#include <iostream>

ConcreteObserverA_ThirdVer::ConcreteObserverA_ThirdVer(Subject* subject) : mSubject(subject)
{
}

ConcreteObserverA_ThirdVer::~ConcreteObserverA_ThirdVer()
{
        if (mSubject)
                mSubject = nullptr;
}

void ConcreteObserverA_ThirdVer::update(Subject* subject, const std::string& info)
{
        if (subject && subject == mSubject)
        {
                if (info == "有美女!")
                {
                        std::cout << "哇~" << std::endl;
                }
                else
                {
                        std::cout << "(ˉ▽ ̄~) 切~~" << std::endl;
                }
        }
}


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 用C++实现观察者模式的几种变体