C++观察者模式(Observer)

 C++
时间:

使用场景

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

一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

一个对象必须通知其他对象,而并不知道这些对象是谁。

需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

Observer

Subject.h

#ifndef __SUBJECT_H__
#define __SUBJECT_H__

#include <list>
#include <string>

using namespace std;

typedef string State;

class Observer;

class CSubject
{
    public:
        virtual ~CSubject();
        virtual void Attach(Observer* obv);
        virtual void Detach(Observer* obv);
        virtual void Notify();
        virtual void SetState(const State& st) = 0;
        virtual State GetState() = 0;
    protected:
        CSubject();
    private:
        list<Observer*>* _obvs;
};

class ConcreteSubject : public CSubject
{
    public:
        ConcreteSubject();
        ~ConcreteSubject();
        State GetState();
        void SetState(const State& st);
    protected:
    private:
        State _st;
};

#endif

Subject.cpp

#include "Subject.h"
#include "Observer.h"

#include <iostream>

using namespace std;

typedef string state;

CSubject::~CSubject()
{

}

void CSubject::Attach(Observer* obv)
{
    _obvs->push_front(obv);
}

void CSubject::Detach(Observer* obv)
{
    if(obv != nullptr)
        _obvs->remove(obv);
}

void CSubject::Notify()
{
    list<Observer*>::iterator it;
    it = _obvs->begin();

    for(; it != _obvs->end(); it++)
    {
        (*it)->Update(this);
    }
}

CSubject::CSubject()
{
    _obvs = new list<Observer*>;
}

ConcreteSubject::ConcreteSubject()
{
    _st = '\0';
}

ConcreteSubject::~ConcreteSubject()
{

}

State ConcreteSubject::GetState()
{
    return _st;
}

void ConcreteSubject::SetState(const State& st)
{
    _st = st;
}

Observer.h

#ifndef __OBSERVER_H__
#define __OBSERVER_H__

#include "Subject.h"

#include<string>

using namespace std;

typedef string State;

class Observer
{
    public:
        virtual ~Observer() { _st = '\0'; }
        virtual void Update(CSubject* sub) = 0;
        virtual void PrintInfo() = 0;
    protected:
        Observer() {}
        State _st;
    private:
};

class ConcreteObserverA : public Observer
{
    public:
        virtual CSubject* GetSubject();
        ConcreteObserverA(CSubject* sub);
        virtual ~ConcreteObserverA();
        void Update(CSubject* sub);
        void PrintInfo();
    protected:
    private:
        CSubject* _sub;
};

class ConcreteObserverB : public Observer
{
    public:
        virtual CSubject* GetSubject();
        ConcreteObserverB(CSubject* sub);
        virtual ~ConcreteObserverB();
        void Update(CSubject* sub);
        void PrintInfo();
    protected:
    private:
        CSubject* _sub;
};


#endif

Observer.cpp

#include"Observer.h"
#include"Subject.h"

#include <iostream>
#include <string>

using namespace std;

CSubject* ConcreteObserverA::GetSubject()
{
    return _sub;
}

ConcreteObserverA::ConcreteObserverA(CSubject* sub)
{
    _sub = sub;
    _sub->Attach(this);
}

ConcreteObserverA::~ConcreteObserverA()
{
    _sub->Detach(this);
    if(_sub != nullptr)
        delete _sub;
}

void ConcreteObserverA::Update(CSubject* sub)
{
    _st = sub->GetState();

    PrintInfo();
}

void ConcreteObserverA::PrintInfo()
{
    cout << "ConcreteObserverA Observer......"  << _sub->GetState() << endl;
}




CSubject* ConcreteObserverB::GetSubject()
{
    return _sub;
}

ConcreteObserverB::ConcreteObserverB(CSubject* sub)
{
    _sub = sub;
    _sub->Attach(this);
}

ConcreteObserverB::~ConcreteObserverB()
{
    _sub->Detach(this);
    if(_sub != nullptr)
        delete _sub;
}

void ConcreteObserverB::Update(CSubject* sub)
{
    _st = sub->GetState();

    PrintInfo();
}

void ConcreteObserverB::PrintInfo()
{
    cout << "ConcreteObserverB Observer......"  << _sub->GetState() << endl;
}

main.cpp

#include"Observer.h"
#include"Subject.h"

int main(int argc, char* argv[])
{
    ConcreteSubject* sub = new ConcreteSubject();

    Observer* o1 = new ConcreteObserverA(sub);
    Observer* o2 = new ConcreteObserverB(sub);
    sub->SetState("old");
    sub->Notify();
    sub->SetState("new");
    sub->Notify();
    return 0;
}

0 评论