-----------------------------------------------------------------------------
[Observer]
의도:
일대다의 관련성을 갖는 객체들의 경우 한 객체의 상태가 변하면 다른 모든 객체에 그 사항을
알리고 필요한 수정이 자동으로 이루어지도록 할 수 있어야 한다.
다른 이름:
Dependent, Publish-Subject
설명:
MFC의 CView::OnUpdate(), CDocument::UpdateAllViews()와 같은 개념으로 MVC 모델에서
One-Document에 Multi-View모델을 생각하면 쉽다. 이 때 Document는 Subject이고 View는
Observer이다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Observer
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <list>
#include <algorithm>
/////////////////////////////////////////////////////////////////////////////
//
// Observer
//
/////////////////////////////////////////////////////////////////////////////
class Subject;
class Observer
{
public:
virtual ~Observer() {}
public:
virtual void Update (Subject* s) = 0;
};
class Subject
{
public:
virtual ~Subject() {}
public:
void Attach (Observer *o)
{
Observers_.push_back (o);
}
void Detach (Observer *o)
{
std::list<Observer*>::iterator i;
i = std::find (Observers_.begin(), Observers_.end(), o);
if (i!=Observers_.end())
{
Observers_.erase (i);
}
}
void Notify (void)
{
std::list<Observer*>::iterator i;
for (i=Observers_.begin(); i!=Observers_.end(); i++)
{
(*i)->Update (this);
}
}
private:
std::list<Observer*> Observers_;
};
////-------------------------------------------------------------------------
class ConcreteSubject : public Subject
{
public:
void SetState (std::string s)
{
State_ = s;
Notify ();
}
std::string GetState (void) const
{
return State_;
}
private:
std::string State_;
};
class ConcreteObserverA : public Observer
{
public:
explicit ConcreteObserverA(ConcreteSubject* s) : Subject_(s)
{
Subject_->Attach (this);
}
virtual ~ConcreteObserverA()
{
Subject_->Detach (this);
}
public:
virtual void Update (Subject* s)
{
if (s==Subject_)
{
std::cout << "ConcreteObserverA::Update(): Subject_->GetState()="
<< Subject_->GetState().c_str()
<< std::endl;
}
}
protected:
ConcreteSubject *Subject_;
};
class ConcreteObserverB : public Observer
{
public:
explicit ConcreteObserverB (ConcreteSubject* s) : Subject_(s)
{
Subject_->Attach (this);
}
virtual ~ConcreteObserverB()
{
Subject_->Detach (this);
}
public:
virtual void Update (Subject* s)
{
if (s==Subject_)
{
std::cout << "ConcreteObserverB::Update(): Subject_->GetState()="
<< Subject_->GetState().c_str()
<< std::endl;
}
}
protected:
ConcreteSubject *Subject_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
ConcreteSubject subject;
ConcreteObserverA observerA(&subject);
ConcreteObserverB observerB(&subject);
subject.SetState ("one");
subject.SetState ("two");
subject.SetState ("three");
return 0;
}
-----------------------------------------------------------------------------
ConcreteObserverA::Update(): Subject_->GetState()=one
ConcreteObserverB::Update(): Subject_->GetState()=one
ConcreteObserverA::Update(): Subject_->GetState()=two
ConcreteObserverB::Update(): Subject_->GetState()=two
ConcreteObserverA::Update(): Subject_->GetState()=three
ConcreteObserverB::Update(): Subject_->GetState()=three