はじめに
大規模なソフトウェアを読んでいて、Observer Patternのコードを読むといつも迷子になってしまう。
何かしらのイベントが発生すると、Subjectに事前に登録されているインスタンスのメソッドを呼び出す(本記事ではupdateメソッド)が、いつ、どこで、どんなインスタンスがSubjectに登録されたかは、Subjectのクラスだけを見てもわからない。
Observer Patternの全体の流れを理解して、
Subjectを生成している初期化処理が別の場所にあるので、そこを見なければいけない(本記事ではmain関数)。
Observer Pattern
知らせる側(Subject)が通知先(Observer,Listener)を事前に登録しておいて、
Subjectに更新があれば、Observerのメソッドを呼び出すことで、変更を通知する仕組み。
Subject/Observerを生成
Subject/Observerを生成して、SubjectにObserverを登録させる。
Subjectの変化に応じて、Observerのメソッドが暗黙的に呼び出されるようになる。
int main() {
auto sub = make_shared<Subject>(10);
auto obs = make_unique<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;
}
実行時の出力
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の定義
Subject::subscribe(Object)がmainから呼び出さ、内部でObserverを保持する。
Subjectの内部状態が変化する毎に、保持したObserverのupdae()を呼び出す。
class Subject {
public:
Subject(int s) : m_state{s}, m_observers{} {}
virtual ~Subject() = default;
// Subject::subscribe()がmain()から呼ばれる
void subscribe(Observer* x) {
x->setObject(this);
m_observers.push_back(x);
}
int getState() const {
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の定義
ObserverがSubjectを持てるようにsetObject()を用意する。
Subjectの変化時にupdate()が呼び出される。
class Observer {
public:
Observer() = default;
virtual ~Observer() = default;
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;
}
コード全文
# include<iostream>
# include<vector>
# include<memory>
using namespace std;
class Subject;
class Observer {
public:
Observer() = default;
virtual ~Observer() = default;
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}, m_observers{} {}
virtual ~Subject() = default;
// Subject::subscribe()がmain()から呼ばれる
void subscribe(Observer* x){
x->setObject(this);
m_observers.push_back(x);
}
int getState(){
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() {
auto sub = make_shared<Subject>(10);
auto obs = make_unique<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;
}
