设计模式 - Observer实现
Observer模式的典型实现:
Subject.h NOTE:1.Subject类依赖Obserer接口类。2.Attach又叫Register/Subscribe/AddObserver,Detach又叫Release/Unsubscribe/RemoveObserver。TODO:Attach方法应该判断一个Observer有没有被重复添加。Detach应确保Obserer存在。考虑Subject对象销毁如何通知Observer。
#ifndef DP_SUBJECT_H #define DP_SUBJECT_H #include "Observer.h" #include <list> class Subject { public: virtual ~Subject() { delete observers; } virtual void Attach(Observer* observer) { observers->push_front(observer); } virtual void Detach(Observer* observer) { observers->remove(observer); } virtual void Notify() { std::list<Observer*>::iterator it; for (it = observers->begin(); it != observers->end(); ++it) { (*it)->Update(this); } }
protected: Subject() { observers = new std::list<Observer*>; } private: std::list<Observer*>* observers; }; #endif
Observer.h
#ifndef DP_OBSERVER_H #define DP_OBSERVER_H class Subject; class Observer { public: virtual ~Observer() { } virtual void Update(Subject* subject) = 0; protected: Observer() { } }; #endif
ConcreteSubject.h NOTE:SetState方法里直接调用Notify可以减轻用户负担。
#ifndef DP_CONCRETESUBJECT_H #define DP_CONCRETESUBJECT_H #include "Subject.h" #include <string>
class ConcreteSubject : public Subject { public: ConcreteSubject() : subjectState("") { } void SetState(const std::string& state) { subjectState = state; } std::string GetState() { return subjectState; } private: std::string subjectState; }; #endif
ConcreteObserver.h NOTE:1.细节通过调用GetState向ConcreteSubject查询,属于拉模型。2.要是Update参数包括全部或部分细节,则是推模型。3.定义一个Collection成员存储多个Subject,不在构造函数里初始化绑定Subject,而是通过动态的方式注册,可以实现观察多个Subject。 TODO:Update函数应该对dynamic_cast的异常情况进行处理。
#ifndef DP_CONCRETEOBSERVER_H #define DP_CONCRETEOBSERVER_H #include "Observer.h" #include <string>
class ConcreteSubject;
class ConcreteObserver : public Observer { public: ConcreteObserver(Subject* subject) : observerState("") { this->subject = subject; subject->Attach(this); } virtual ~ConcreteObserver() { subject->Detach(this); delete subject; } virtual void Update(Subject* subject) {
if (this->subject == subject) { observerState = dynamic_cast<ConcreteSubject*>(subject)->GetState();
} } private: Subject* subject; std::string observerState; }; #endif
Main.cpp
#include "ConcreteSubject.h" #include "ConcreteObserver.h" int main() { ConcreteSubject* subject = new ConcreteSubject(); Observer* observer1 = new ConcreteObserver(subject); Observer* observer2 = new ConcreteObserver(subject); subject->SetState("A"); subject->Notify(); subject->SetState("B"); subject->Notify(); return 0; }