Observer pattern - meruneru/tech_memo GitHub Wiki
知らせる側(Subject)が通知先(Observer,Listener)を事前に登録しておいて、
Subjectに更新があれば、Observerのメソッドを呼び出すことで、変更を通知する仕組み。
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
class Subject;
class Observer{
public:
Observer(void){}
virtual ~Observer(void){}
void setObject(Subject* s){
m_subject.reset(s);
}
void update();
private:
unique_ptr<Subject> m_subject;
};
class Subject{
public:
Subject(int s){m_state=s;}
virtual ~Subject(void){};
// Subject::subscribe()がmain()から呼ばれる
void subscribe(Observer* x){
x->setObject(this);
m_observers.push_back(x);
}
int getState(void){
return m_state;
}
void setState(int s){
m_state=s;
notify();
}
private:
void notify(){
for(auto& i: m_observers){
i->update();
}
}
int m_state;
vector<Observer*> m_observers;
};
void Observer::update(){
cout<<"Observer was notified update:"<<m_subject->getState()<< endl;
}
int main(){
shared_ptr<Subject> sub(new Subject(10));
unique_ptr<Observer> obs(new Observer());
sub->subscribe(obs.get());
cout<<"current state:"<<sub->getState()<<endl;
sub->setState(15);
cout<<"current state:"<<sub->getState()<<endl;
sub->setState(20);
cout<<"current state:"<<sub->getState()<<endl;
sub->setState(25);
cout<<"current state:"<<sub->getState()<<endl;
return 0;
}
Subject/Observerを生成して、SubjectにObserverを登録させる。
Subjectの変化に応じて、Observerのメソッドが暗黙的に呼び出されるようになる。
int main(){
shared_ptr<Subject> sub(new Subject(10));
unique_ptr<Observer> obs(new Observer());
sub->subscribe(obs.get());
cout<<"current state:"<<sub->getState()<<endl;
sub->setState(15);
cout<<"current state:"<<sub->getState()<<endl;
sub->setState(20);
cout<<"current state:"<<sub->getState()<<endl;
sub->setState(25);
cout<<"current state:"<<sub->getState()<<endl;
return 0;
}
実行時の出力
current state:10
Observer was notified update:15
current state:15
Observer was notified update:20
current state:20
Observer was notified update:25
current state:25
Subject::subscribe(Object)がmainから呼び出さ、内部でObserverを保持する。
Subjectの内部状態が変化する毎に、保持したObserverのupdae()を呼び出す。
class Subject{
public:
Subject(int s){m_state=s;}
virtual ~Subject(void){};
// Subject::subscribe()がmain()から呼ばれる
void subscribe(Observer* x){
x->setObject(this);
m_observers.push_back(x);
}
int getState(void){
return m_state;
}
void setState(int s){
m_state=s;
notify();
}
private:
void notify(){
for(auto& i: m_observers){
i->update();
}
}
int m_state;
vector<Observer*> m_observers;
};
ObserverがSubjectを持てるようにsetObject()を用意する。
Subjectの変化時にupdate()が呼び出される。
class Observer{
public:
Observer(void){}
virtual ~Observer(void){}
void setObject(Subject* s){
m_subject.reset(s);
}
void update();
private:
unique_ptr<Subject> m_subject;
}
// CallBack
void Observer::update(){
cout<<"Observer was notified update:"<<m_subject->getState()<< endl;
}