행위패턴-Observer

2008. 8. 16. 17:17 from 셈말짓기/GoF

-----------------------------------------------------------------------------
[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

Posted by 셈말짓기 :