GoF's Design Patterns를 다시 공부하면서 그 동안 만들어 놓은 Sample들이다.
UML로 표시된 구조를 가급적 맞추려고 노력해서 실제 Pattern들이 의미하는 바를 표현하기에는 역부족이다.
Sample Code를 보면서 구조는 쉽게 이해는 할 수 있을지 몰라도 Pattern들의 실제적인 의미나 사용을 하기
위해서는 책을 참고하는 것이 도움이 될 것 이다.
-----------------------------------------------------------------------------
[Interpreter]
의도:
어떤 언어는 문법에 대한 표현을 정의하면서 그 언어로 기술된 문장을 해석하는 기법을 표현하기
위해서 인터프리터도 함께 정의하는 경우가 있다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Interpreter
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <string>
#include <list>
#include <deque>
#include <vector>
#include <map>
#include <iostream>
/////////////////////////////////////////////////////////////////////////////
//
// Interpreter
//
//
/////////////////////////////////////////////////////////////////////////////
class Context
{
public:
std::map<std::string, bool> Variables_;
};
class AbstractExpression
{
public:
virtual bool Interpret(Context&) = 0;
};
class TerminalExpression_Variable: public AbstractExpression
{
public:
explicit TerminalExpression_Variable (std::string n) : Name_(n)
{
}
public:
virtual bool Interpret(Context& context)
{
return context.Variables_[Name_];
}
private:
std::string Name_;
};
class NonterminalExpression_And: public AbstractExpression
{
public:
NonterminalExpression_And (AbstractExpression* p1, AbstractExpression* p2) :
Operand1_(p1),
Operand2_(p2)
{
}
public:
virtual bool Interpret(Context& context)
{
return Operand1_->Interpret(context) && Operand2_->Interpret(context);
}
private:
AbstractExpression* Operand1_;
AbstractExpression* Operand2_;
};
class NonterminalExpression_Or: public AbstractExpression
{
public:
NonterminalExpression_Or (AbstractExpression* p1, AbstractExpression* p2) :
Operand1_(p1),
Operand2_(p2)
{
}
public:
virtual bool Interpret(Context& context)
{
return Operand1_->Interpret(context) || Operand2_->Interpret(context);
}
private:
AbstractExpression* Operand1_;
AbstractExpression* Operand2_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
bool _tmain(bool argc, _TCHAR* argv[])
{
Context context;
context.Variables_["A"] = 1;
context.Variables_["B"] = 1;
context.Variables_["C"] = 0;
TerminalExpression_Variable a("A");
TerminalExpression_Variable b("B");
TerminalExpression_Variable c("C");
NonterminalExpression_Or exp1 (&a, &b);
NonterminalExpression_And exp2 (&exp1, &c);
bool result = exp2.Interpret(context);
std::cout << "result=" << result << std::endl;
return 0;
};
-----------------------------------------------------------------------------
result=0
-----------------------------------------------------------------------------
[Singleton]
의도:
클래스에서 만들 수 있는 인스턴스가 오직 하나일 경우에 이에 대한 접근은 어디에서든지
하나로만 통일하여 제공한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Singleton
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Singleton
//
//
/////////////////////////////////////////////////////////////////////////////
class Singleton
{
protected:
Singleton () {}
public:
virtual ~Singleton() {}
public:
static Singleton& Instance(void)
{
if (Instance_.get() == 0)
{
Instance_.reset( new Singleton() );
}
return *Instance_;
}
private:
static std::auto_ptr<Singleton> Instance_;
public:
void Operation (void)
{
std::cout << "Singleton::Operation()" << std::endl;
}
};
std::auto_ptr<Singleton> Singleton::Instance_;
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Singleton::Instance().Operation();
return 0;
}
-----------------------------------------------------------------------------
Singleton::Operation()
-----------------------------------------------------------------------------
[Prototype]
의도:
견본적(prototypical) 인스턴스를 사용하여 생성할 객체의 종류를 명시하고 이렇게 만들어진
견본을 복사해서 새로운 객체를 생성한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Prototype
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Prototype
//
//
/////////////////////////////////////////////////////////////////////////////
class Product
{
public:
Product() {}
virtual ~Product() {}
public:
virtual Product* Clone (void) = 0;
virtual void Show (void) = 0;
};
class ConcreteProductA : public Product
{
public:
explicit ConcreteProductA(int v) : Value_(v) {}
virtual ~ConcreteProductA() {}
public:
virtual Product* Clone (void)
{
return new ConcreteProductA(Value_);
}
virtual void Show (void)
{
std::cout << "ConcreteProductA::Show(): " << Value_ << std::endl;
}
private:
int Value_;
};
class ConcreteProductB : public Product
{
public:
explicit ConcreteProductB(int v) : Value_(v) {}
virtual ~ConcreteProductB() {}
public:
virtual Product* Clone (void)
{
return new ConcreteProductB(Value_);
}
virtual void Show (void)
{
std::cout << "ConcreteProductB::Show(): " << Value_ << std::endl;
}
private:
int Value_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Factory
//
//
/////////////////////////////////////////////////////////////////////////////
class ProductFactory
{
public:
ProductFactory()
{
ProductA_.reset ( new ConcreteProductA(100) );
ProductB_.reset ( new ConcreteProductB(200) );
}
public:
Product* CreateA (void)
{
return ProductA_->Clone();
}
Product* CreateB (void)
{
return ProductB_->Clone();
}
private:
std::auto_ptr<Product> ProductA_;
std::auto_ptr<Product> ProductB_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<Product> p;
ProductFactory f;
p.reset ( f.CreateA() );
p->Show();
std::cout << std::endl;
p.reset ( f.CreateB() );
p->Show();
return 0;
}
ConcreteProductB::Show(): 200
-----------------------------------------------------------------------------
[Factory Method]
의도:
객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한
결정은 서브클래스에서 이루어지도록 Factory Method 패턴은 서브클래스에게 인스턴스 생성의
책임을 미룬다.
다른 이름:
Virtual Constructor
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Factory Method
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Product
//
//
/////////////////////////////////////////////////////////////////////////////
class Product
{
public:
Product() {}
virtual ~Product() {}
public:
virtual void Operation (void) = 0;
};
class ConcreteProductA : public Product
{
public:
ConcreteProductA(){}
virtual ~ConcreteProductA() {}
public:
virtual void Operation (void)
{
std::cout << "ConcreteProductA::Operation()" << std::endl;
}
};
class ConcreteProductB : public Product
{
public:
ConcreteProductB(){}
virtual ~ConcreteProductB() {}
public:
virtual void Operation (void)
{
std::cout << "ConcreteProductB::Operation()" << std::endl;
}
};
class ConcreteProductB_2 : public Product
{
public:
ConcreteProductB_2(){}
virtual ~ConcreteProductB_2() {}
public:
virtual void Operation (void)
{
std::cout << "ConcreteProductB_2::Operation()" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Factory Method
//
//
/////////////////////////////////////////////////////////////////////////////
enum ProductID
{
Id_ConcreteProductA,
Id_ConcreteProductB
};
class Createor
{
public:
virtual ~Createor() {}
public:
virtual std::auto_ptr<Product> Create (ProductID id)
{
if (Id_ConcreteProductA==id)
return std::auto_ptr<Product> ( new ConcreteProductA() );
if (Id_ConcreteProductB==id)
return std::auto_ptr<Product> ( new ConcreteProductB() );
return std::auto_ptr<Product>();
}
};
class ConcreteCreateor : public Createor
{
public:
virtual std::auto_ptr<Product> Create (ProductID id)
{
if (Id_ConcreteProductB==id)
return std::auto_ptr<Product> ( new ConcreteProductB_2() );
return Createor::Create(id);
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<Createor> c;
std::auto_ptr<Product> p;
std::cout << "Created by Createor()" << std::endl;
c.reset ( new Createor() );
p = c->Create ( Id_ConcreteProductA );
p->Operation ();
p = c->Create ( Id_ConcreteProductB );
p->Operation ();
std::cout << std::endl;
std::cout << "Created by ConcreteCreateor()" << std::endl;
c.reset ( new ConcreteCreateor() );
p = c->Create ( Id_ConcreteProductA );
p->Operation ();
p = c->Create ( Id_ConcreteProductB );
p->Operation ();
std::cout << std::endl;
return 0;
}
-----------------------------------------------------------------------------
Created by Createor()
ConcreteProductA::Operation()
ConcreteProductB::Operation()
Created by ConcreteCreateor()
ConcreteProductA::Operation()
ConcreteProductB_2::Operation()
-----------------------------------------------------------------------------
[Builder]
-----------------------------------------------------------------------------
복잡한 객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여 서로 다른
표현이라도 이를 생성할 수 있는 동일한 구축 공정을 제공할 수 있도록 한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Builder
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Builder
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Builder
//
//
/////////////////////////////////////////////////////////////////////////////
class Product
{
public:
Product() :
PartA_(0),
PartB_(0),
PartC_(0)
{
}
virtual ~Product()
{
}
public:
void SetPartA (int a) { PartA_= a; }
void SetPartB (int b) { PartB_= b; }
void SetPartC (int c) { PartC_= c; }
void Operation (void)
{
std::cout << "[Product]" << std::endl
<< "PartA=" << PartA_ << std::endl
<< "PartB=" << PartB_ << std::endl
<< "PartC=" << PartC_ << std::endl
<< std::endl;
}
private:
int PartA_;
int PartB_;
int PartC_;
};
//// ------------------------------------------------------------------------
class AbstractBuilder
{
public:
virtual ~AbstractBuilder() {}
public:
std::auto_ptr<Product> GetResult (void)
{
return Product_;
}
void NewProduct (void)
{
Product_.reset ( new Product() );
}
public:
virtual void BuildPartA (void)=0;
virtual void BuildPartB (void)=0;
virtual void BuildPartC (void)=0;
protected:
std::auto_ptr<Product> Product_;
};
class ConcreteBuilderA : public AbstractBuilder
{
public:
virtual void BuildPartA (void) { Product_->SetPartA(1); }
virtual void BuildPartB (void) { Product_->SetPartB(2); }
virtual void BuildPartC (void) { Product_->SetPartC(3); }
};
class ConcreteBuilderB : public AbstractBuilder
{
public:
virtual void BuildPartA (void) { Product_->SetPartA(4); }
virtual void BuildPartB (void) { Product_->SetPartB(5); }
virtual void BuildPartC (void) { Product_->SetPartC(6); }
};
//// ------------------------------------------------------------------------
class Director
{
public:
Director() : Builder_(0) {}
virtual ~Director() {}
public:
void SetBuilder (AbstractBuilder* b)
{
Builder_ = b;
}
void Construct (void)
{
Builder_->NewProduct ();
Builder_->BuildPartA ();
Builder_->BuildPartB ();
Builder_->BuildPartC ();
}
private:
AbstractBuilder* Builder_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Director director;
ConcreteBuilderA builder_A;
ConcreteBuilderB builder_B;
std::auto_ptr<Product> product;
director.SetBuilder (&builder_A);
director.Construct ();
product = builder_A.GetResult();
product->Operation();
director.SetBuilder (&builder_B);
director.Construct ();
product = builder_B.GetResult();
product->Operation();
return 0;
}
[Product]
PartA=4
PartB=5
PartC=6
-----------------------------------------------------------------------------
[Abstract Factory]
의도:
구체적 클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 군을 생성하기
위한 인터페이스를 제공한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Abstract Factory
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Abstract Factory
//
//
/////////////////////////////////////////////////////////////////////////////
class AbstractProdcutA
{
public:
AbstractProdcutA () {}
virtual ~AbstractProdcutA() {}
};
class AbstractProdcutB
{
public:
AbstractProdcutB () {}
virtual ~AbstractProdcutB() {}
};
class AbstractFactory
{
public:
virtual AbstractProdcutA* CreateProductA (void) = 0;
virtual AbstractProdcutB* CreateProductB (void) = 0;
};
//// ------------------------------------------------------------------------
class ProdcutA1 : public AbstractProdcutA
{
public:
ProdcutA1()
{
std::cout << "ProdcutA1()" << std::endl;
}
};
class ProdcutA2 : public AbstractProdcutA
{
public:
ProdcutA2()
{
std::cout << "ProdcutA2()" << std::endl;
}
};
class ProdcutB1 : public AbstractProdcutB
{
public:
ProdcutB1()
{
std::cout << "ProdcutB1()" << std::endl;
}
};
class ProdcutB2 : public AbstractProdcutB
{
public:
ProdcutB2()
{
std::cout << "ProdcutB2()" << std::endl;
}
};
//// ------------------------------------------------------------------------
class ConcreteFactory1 : public AbstractFactory
{
public:
virtual AbstractProdcutA* CreateProductA (void)
{
return new ProdcutA1();
}
virtual AbstractProdcutB* CreateProductB (void)
{
return new ProdcutB1();
}
};
class ConcreteFactory2 : public AbstractFactory
{
virtual AbstractProdcutA* CreateProductA (void)
{
return new ProdcutA2();
}
virtual AbstractProdcutB* CreateProductB (void)
{
return new ProdcutB2();
}
};
//// ------------------------------------------------------------------------
class Client
{
public:
void Create (AbstractFactory *f)
{
ProdcutA_.reset( f->CreateProductA() );
ProdcutB_.reset( f->CreateProductB() );
}
private:
std::auto_ptr<AbstractProdcutA> ProdcutA_;
std::auto_ptr<AbstractProdcutB> ProdcutB_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Client client;
std::cout << "by ConcreteFactory1" << std::endl;
client.Create ( &ConcreteFactory1() );
std::cout << std::endl;
std::cout << "by ConcreteFactory2" << std::endl;
client.Create ( &ConcreteFactory2() );
return 0;
}
-----------------------------------------------------------------------------
by ConcreteFactory1
ProdcutA1()
ProdcutB1()
by ConcreteFactory2
ProdcutA2()
ProdcutB2()
-----------------------------------------------------------------------------
[Proxy]
의도:
다른 객체에 접근하기 위해 중간 대리 역활을 하는 객체를 둔다.
다른 이름:
Surrogate
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Proxy
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <list>
#include <algorithm>
#define USE_HANDLE 1
#if (USE_HANDLE==1)
/////////////////////////////////////////////////////////////////////////////
//
// Handle
//
/////////////////////////////////////////////////////////////////////////////
template<typename T>
class CRefCountedInstance
{
public:
CRefCountedInstance ();
public:
inline void AddRef (void);
inline void Release (void);
inline void Assign (T *p);
inline bool IsReferenced (void);
inline T* GetInstance (void);
private:
T *Instance_;
int RefCount_;
};
template<typename T>
CRefCountedInstance<T>::CRefCountedInstance () :
RefCount_ (0),
Instance_ (0)
{
}
template<typename T>
void CRefCountedInstance<T>::AddRef (void)
{
RefCount_++;
}
template<typename T>
void CRefCountedInstance<T>::Release (void)
{
if (RefCount_>0)
{
RefCount_--;
}
if (RefCount_==0)
{
if (Instance_)
{
delete Instance_;
}
Instance_ = 0;
}
}
template<typename T>
void CRefCountedInstance<T>::Assign (T *p)
{
Instance_ = p;
AddRef ();
}
template<typename T>
bool CRefCountedInstance<T>::IsReferenced (void)
{
if (RefCount_==0)
return false;
return true;
}
template<typename T>
T* CRefCountedInstance<T>::GetInstance (void)
{
return Instance_;
}
template<typename T>
class Handle
{
public:
Handle ();
explicit Handle (T *p);
Handle (const Handle<T> ©);
virtual ~Handle ();
public:
Handle<T>& operator = (const Handle<T>& rhs);
public:
inline T& operator* () const;
inline T* operator-> () const;
inline T* Get (void) const;
private:
CRefCountedInstance<T>* Rep_;
};
template<typename T>
Handle<T>::Handle () : Rep_(0)
{
}
template<typename T>
Handle<T>::Handle (T *p)
{
Rep_ = new CRefCountedInstance<T>();
Rep_->Assign(p);
}
template<typename T>
Handle<T>::Handle (const Handle<T> ©)
{
Rep_ = copy.Rep_;
if (Rep_)
Rep_->AddRef ();
}
template<typename T>
Handle<T>::~Handle ()
{
if (Rep_)
{
Rep_->Release ();
if (!Rep_->IsReferenced())
delete Rep_;
}
}
template<typename T>
Handle<T>& Handle<T>::operator = (const Handle<T>& rhs)
{
if (this == &rhs) return *this;
if (Rep_)
Rep_->Release ();
Rep_ = rhs.Rep_;
if (Rep_)
Rep_->AddRef ();
return *this;
}
template<typename T>
T& Handle<T>::operator*() const
{
return *(Rep_->GetInstance());
}
template<typename T>
T* Handle<T>::operator -> () const
{
if (Rep_==0)
return 0;
return (Rep_->GetInstance());
}
template<typename T>
T* Handle<T>::Get (void) const
{
if (Rep_==0)
return 0;
return (Rep_->GetInstance());
}
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Proxy
//
/////////////////////////////////////////////////////////////////////////////
class Subject
{
public:
virtual ~Subject() {}
public:
virtual void Request (void) = 0;
virtual void SetData (int ) = 0;
};
class RealSubject : public Subject
{
public:
explicit RealSubject (int n) :
Data_ (n)
{
std::cout << "RealSubject::RealSubject(" << Data_ << ")" << std::endl;
}
virtual ~RealSubject ()
{
std::cout << "RealSubject::~RealSubject(" << Data_ << ")" << std::endl;
}
public:
virtual void Request (void)
{
std::cout << "RealSubject::Request(): Data_ = " << Data_ << std::endl;
}
virtual void SetData (int n)
{
Data_ = n;
}
private:
int Data_;
};
#if (USE_HANDLE==1)
class Proxy :
public Subject
{
public:
Proxy() : SubjectData_(0)
{
}
explicit Proxy (int n) :
SubjectData_ (n)
{
}
Proxy (const Proxy ©)
{
const_cast<Proxy&>(copy).Load();
SubjectData_ = copy.SubjectData_;
Subject_ = copy.Subject_;
}
virtual ~Proxy () {}
public:
virtual void Request (void)
{
GetSubject()->Request();
}
virtual void SetData (int n)
{
GetSubject()->SetData(n);
}
private:
Subject* GetSubject (void)
{
if (Subject_.Get()==0)
{
Handle<Subject> s ( new RealSubject(SubjectData_) );
Subject_ = s;
}
return Subject_.Get();
}
public:
void Load (void)
{
GetSubject();
}
public:
Proxy& operator = (const Proxy& rhs)
{
if (this == &rhs) return *this;
const_cast<Proxy&>(rhs).Load();
SubjectData_ = rhs.SubjectData_;
Subject_ = rhs.Subject_;
return *this;
}
private:
Handle<Subject> Subject_;
int SubjectData_;
};
#else
class Proxy :
public Subject
{
public:
Proxy() :
SubjectData_(0),
Subject_ (0)
{
}
explicit Proxy (int n) :
SubjectData_ (n),
Subject_ (0)
{
}
virtual ~Proxy ()
{
if (Subject_)
delete Subject_;
}
public:
virtual void Request (void)
{
GetSubject()->Request();
}
virtual void SetData (int n)
{
GetSubject()->SetData(n);
}
private:
Subject* GetSubject (void)
{
if (Subject_==0)
{
Subject_ = new RealSubject(SubjectData_);
}
return Subject_;
}
private:
Subject *Subject_;
int SubjectData_;
};
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
#if (USE_HANDLE==1)
std::cout << "(USE_HANDLE==1)" << std::endl << std::endl;
Proxy a(1);
Proxy b;
Proxy c;
std::cout << "a.Load();" << std::endl;
//a.Load();
std::cout << std::endl;
std::cout << "b=a;" << std::endl;
b=a;
std::cout << std::endl;
std::cout << "a.Request ();" << std::endl;
a.Request ();
std::cout << std::endl;
std::cout << "a.SetData (2);" << std::endl;
a.SetData (2);
std::cout << std::endl;
std::cout << "b.Request ();" << std::endl;
b.Request ();
std::cout << std::endl;
std::cout << "c=a" << std::endl;
c=a;
std::cout << "c.Request()" << std::endl;
c.Request ();
std::cout << std::endl;
#else
std::cout << "(USE_HANDLE==0)" << std::endl << std::endl;
Proxy a(1);
RealSubject b(2);
std::cout << std::endl;
std::cout << "a.Request()" << std::endl;
a.Request (); // late creating instance
std::cout << std::endl;
std::cout << "a.Request()" << std::endl;
b.Request ();
std::cout << std::endl;
#endif
return 0;
}
-----------------------------------------------------------------------------
(USE_HANDLE==1)
a.Load();
RealSubject::RealSubject(1)
b=a;
a.Request ();
RealSubject::Request(): Data_ = 1
a.SetData (2);
b.Request ();
RealSubject::Request(): Data_ = 2
c=a
c.Request()
RealSubject::Request(): Data_ = 2
RealSubject::~RealSubject(2)
-----------------------------------------------------------------------------
(USE_HANDLE==0)
RealSubject::RealSubject(2)
a.Request()
RealSubject::RealSubject(1)
RealSubject::Request(): Data_ = 1
a.Request()
RealSubject::Request(): Data_ = 2
RealSubject::~RealSubject(2)
RealSubject::~RealSubject(1)
-----------------------------------------------------------------------------
[Flyweight]
의도:
대규모의 미세한 객체들을 효과적으로 사용하기 위해서는 공유 개념을 도입
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Flyweight
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <list>
#include <algorithm>
/////////////////////////////////////////////////////////////////////////////
//
// Flyweight
//
/////////////////////////////////////////////////////////////////////////////
class Flyweight
{
public:
virtual ~Flyweight() {}
public:
virtual void Operation (void) = 0;
};
class ConcreteFlyweight : public Flyweight
{
public:
ConcreteFlyweight (std::string s, int n) :
Key_ (n),
Value_ (s)
{
}
public:
virtual void Operation (void)
{
std::cout << Value_.c_str() << "(" << Key_ << ")" << std::endl;
}
private:
int Key_;
std::string Value_;
};
class UnsharedConcreteFlyweight : public Flyweight
{
public:
UnsharedConcreteFlyweight (std::string s) :
Value_ (s)
{
}
public:
virtual void Operation (void)
{
std::cout << Value_.c_str() << std::endl;
}
private:
std::string Value_;
};
//// ------------------------------------------------------------------------
class FlyweightFactory
{
private:
struct PoolDeleter
{
public:
PoolDeleter() : Count_(0) {}
public:
void operator()(std::pair<int,Flyweight*> i)
{
Flyweight *p = i.second;
if (p)
{
Count_++;
delete p;
}
}
operator int ()
{
return Count_;
}
private:
int Count_;
};
public:
virtual ~FlyweightFactory ()
{
int Count;
Count = std::for_each(Pool_.begin(), Pool_.end(), PoolDeleter());
std::cout << "~FlyweightFactory(): [ConcreteFlyweight] deleting count="
<< Count
<< std::endl
<< std::endl;
}
public:
Flyweight* GetFlyweight (std::string value, int key)
{
Flyweight* f;
if ( Pool_.end() == Pool_.find (key) )
{
f = new ConcreteFlyweight (value, key);
Pool_[key] = f;
}
else
{
f = Pool_[key];
}
return f;
}
Flyweight* GetUnsharedFlyweight (std::string value)
{
Flyweight* f;
f = new UnsharedConcreteFlyweight ( value );
return f;
}
private:
std::map <int,Flyweight*> Pool_;
};
//// ------------------------------------------------------------------------
class Context
{
private:
template<class T>
struct OperationCaller : public std::unary_function<T, void>
{
public:
void operator()(T ptr)
{
if (ptr)
ptr->Operation();
}
};
template<class T>
struct ListDeleter : public std::unary_function<T, void>
{
public:
ListDeleter() : Count_(0) {}
public:
void operator()(T ptr)
{
if (ptr)
{
if (dynamic_cast<UnsharedConcreteFlyweight*>(ptr))
{
Count_++;
delete ptr;
}
}
}
operator int ()
{
return Count_;
}
private:
int Count_;
};
public:
~Context ()
{
int Count;
Count = std::for_each(List_.begin(), List_.end(), ListDeleter<Flyweight*>());
std::cout << "~Context(): [UnsharedConcreteFlyweight] deleting count="
<< Count
<< std::endl;
}
public:
void Add (std::string s, int n=0)
{
if (n)
List_.push_back ( Factory_.GetFlyweight (s, n) );
else
List_.push_back ( Factory_.GetUnsharedFlyweight (s) );
}
void Operation (void)
{
std::for_each(List_.begin(), List_.end(), OperationCaller<Flyweight*>());
std::cout << std::endl;
}
private:
std::list<Flyweight*> List_;
FlyweightFactory Factory_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Context context;
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Operation ();
return 0;
}
~Context(): [UnsharedConcreteFlyweight] deleting count=5
~FlyweightFactory(): [ConcreteFlyweight] deleting count=1
-----------------------------------------------------------------------------
[Facade]
의도:
서브시스템을 합성하는 다수의 객체들의 인터페이스 집합에 대해 일관된 하나의 인터페이스를
제공할 수 있게 한다. Facade는 서브시스템을 사용하기 쉽게 하기 위한 포괄적 개념의 인터
페이스를 정의 한다.
-----------------------------------------------------------------------------/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Facade
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Subsystem
//
/////////////////////////////////////////////////////////////////////////////
class SubsystemA
{
public:
void OperationA (void)
{
std::cout << "\tSubsystemA::OperationA()" << std::endl;
}
void OperationB (void)
{
std::cout << "\tSubsystemA::OperationB()" << std::endl;
}
};
class SubsystemB
{
public:
void Operation (void)
{
std::cout << "\tSubsystemB::Operation()" << std::endl;
}
};
class SubsystemC
{
public:
void OperationA (void)
{
std::cout << "\tSubsystemC::OperationA()" << std::endl;
}
void OperationB (void)
{
std::cout << "\tSubsystemC::OperationB()" << std::endl;
}
void OperationC (void)
{
std::cout << "\tSubsystemC::OperationC()" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Facade
//
/////////////////////////////////////////////////////////////////////////////
class Facade
{
public:
void OperationA (void)
{
std::cout << "Facade::OperationA()" << std::endl;
A_.OperationA();
B_.Operation ();
C_.OperationA();
std::cout << std::endl;
}
void OperationB (void)
{
std::cout << "Facade::OperationB()" << std::endl;
A_.OperationB();
C_.OperationB();
C_.OperationC();
std::cout << std::endl;
}
private:
SubsystemA A_;
SubsystemB B_;
SubsystemC C_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Facade f;
f.OperationA();
f.OperationB();
return 0;
}
-----------------------------------------------------------------------------Facade::OperationA()
SubsystemA::OperationA()
SubsystemB::Operation()
SubsystemC::OperationA()
Facade::OperationB()
SubsystemA::OperationB()
SubsystemC::OperationB()
SubsystemC::OperationC()
-----------------------------------------------------------------------------
[Decorator]
의도:
객체에 동적으로 새로운 서비스를 추가할 수 있게 한다. Decorator패턴은 기능의 추가를
위해서 서브클래스를 생성하는 것보다 융통성 있는 방법을 제공한다.
다른 이름:
Wrapper
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Decorator
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Decorator
//
//
/////////////////////////////////////////////////////////////////////////////
class Component
{
public:
virtual ~Component() {}
public:
virtual void Operation (void) = 0;
};
class ConcreteComponent : public Component
{
public:
virtual void Operation (void)
{
std::cout << "ConcreteComponent::Operation()" << std::endl;
}
};
class Decorator : public Component
{
public:
explicit Decorator (Component* p) :
Component_(p)
{
}
public:
virtual void Operation (void)
{
if (Component_.get())
Component_->Operation ();
}
private:
std::auto_ptr<Component> Component_;
};
class ConcreteDecoratorA : public Decorator
{
public:
explicit ConcreteDecoratorA (Component* p) :
Decorator(p)
{
}
public:
virtual void Operation (void)
{
Decorator::Operation();
std::cout << "ConcreteDecoratorA::Operation()" << std::endl;
}
};
class ConcreteDecoratorB : public Decorator
{
public:
explicit ConcreteDecoratorB (Component* p) :
Decorator(p)
{
}
public:
virtual void Operation (void)
{
Decorator::Operation();
std::cout << "ConcreteDecoratorB::Operation()" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<Component> p;
p.reset( new ConcreteDecoratorB (
new ConcreteDecoratorA (
new ConcreteComponent())) );
p->Operation ();
return 0;
}
-----------------------------------------------------------------------------
ConcreteComponent::Operation()
ConcreteDecoratorA::Operation()
ConcreteDecoratorB::Operation()
-----------------------------------------------------------------------------
[Bridge]
의도:
구현과 추상화 개념을 분리하려는 것이다. 이로써 구현 자체도 하나의 추상화 개념으로 다양한
변형이 가능해지고, 구현과 독립적으로 인터페이스도 다양함을 가질 수 있게 된다.
다른 이름:
Handle/body
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Bridge
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Bridge
//
/////////////////////////////////////////////////////////////////////////////
class Implementor
{
public:
virtual ~Implementor () {}
public:
virtual void OperationImp (void) = 0;
};
class ConcreteImplementorA : public Implementor
{
public:
virtual void OperationImp (void)
{
std::cout<< "ConcreteImplementorA::OperationImp()" << std::endl;
}
};
class ConcreteImplementorB : public Implementor
{
public:
virtual void OperationImp (void)
{
std::cout<< "ConcreteImplementorB::OperationImp()" << std::endl;
}
};
class ImplementorFactory
{
private:
ImplementorFactory(void) : Env_(0) {};
public:
static ImplementorFactory* Instance (void)
{
if (0==Instance_)
{
Instance_ = new ImplementorFactory();
}
return Instance_;
}
private:
static ImplementorFactory* Instance_;
public:
Implementor* CreateImplementor (void)
{
Implementor* p;
if (Env_==0)
p = new ConcreteImplementorA();
else
p = new ConcreteImplementorB();
return p;
}
public:
void SetEnv (int e)
{
Env_ = e;
}
int GetEnv (void)
{
return Env_;
}
private:
int Env_;
};
ImplementorFactory* ImplementorFactory::Instance_ = 0;
class Abstraction
{
public:
Abstraction () : Imp_(0)
{
}
public:
virtual void Operation (void)
{
GetImp ()->OperationImp();
}
private:
Implementor* GetImp (void)
{
if (Imp_==0)
{
Imp_ = ImplementorFactory::Instance()->CreateImplementor ();
}
return Imp_;
}
private:
Implementor *Imp_;
};
class RefinedAbstraction : public Abstraction
{
public:
virtual void RefinedOperation (void)
{
Abstraction::Operation();
std::cout<< "RefinedAbstraction::RefinedOperation()" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<RefinedAbstraction> p;
p.reset ( new RefinedAbstraction() );
p->RefinedOperation ();
p.reset ();
std::cout << std::endl;
ImplementorFactory::Instance()->SetEnv (1);
p.reset ( new RefinedAbstraction() );
p->RefinedOperation ();
p.reset ();
return 0;
}
-----------------------------------------------------------------------------
ConcreteImplementorA::OperationImp()
RefinedAbstraction::RefinedOperation()
ConcreteImplementorB::OperationImp()
RefinedAbstraction::RefinedOperation()
-----------------------------------------------------------------------------
[Adapter]
의도:
클래스의 인터페이스를 클라이언트가 기대하는 형태의 인터페이스로 변환한다.
어댑터 패턴은 서로 일치하지 않는 인터페이스를 갖는 클래스들을 함께 작동 시킨다.
다른 이름:
Wrapper
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Adapter
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Adapter-1
//
//
/////////////////////////////////////////////////////////////////////////////
class Target
{
public:
virtual ~Target() {}
public:
virtual void Request (void) = 0;
};
class Adaptee
{
public:
void SpecificRequest (void)
{
std::cout << "Adaptee::SpecificRequest()" << std::endl;
}
};
class Adapter_1 :
public Target,
private Adaptee
{
public:
virtual void Request (void)
{
std::cout << "Adaptee::SpecificRequest()" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Adapter-2
//
//
/////////////////////////////////////////////////////////////////////////////
class Adapter_2 :
public Target
{
public:
virtual void Request (void)
{
Adaptee_.SpecificRequest();
}
private:
Adaptee Adaptee_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<Target> t1 ( new Adapter_1() );
std::auto_ptr<Target> t2 ( new Adapter_2() );
t1->Request ();
t2->Request ();
return 0;
}
-----------------------------------------------------------------------------
Adaptee::SpecificRequest()
Adaptee::SpecificRequest()
-----------------------------------------------------------------------------
[Iterator]
의도:
복합 객체 요소들의 내부 표현 방식을 공개하지 않고도 순차적으로 접근할 수 있는 방법을 제공
한다.
다른 이름:
Cursor
설명:
STL의 컨테이너들에 대한 iterator를 생각하면 된다.
-----------------------------------------------------------------------------
GoF에서는 Iterator에 대한 인터페이스를 아래와 같이 표현하고 있다.
template<class Item>
class Iterator
{
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsDone() const = 0;
protected:
Iterator() {};
};
-----------------------------------------------------------------------------
[State]
의도:
객체 자신의 내부 상태에 따라 행위를 변경하도록 한다. 객체가 클래스를 바꾸는 것처럼 보일
수 있다.
다른 이름:
Object for State
설명:
FSM(Finite State Machine)를 구현함에 있어서 State패턴을 이용한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - State
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
/////////////////////////////////////////////////////////////////////////////
//
// State
//
/////////////////////////////////////////////////////////////////////////////
class Context;
class State
{
public:
virtual ~State() {}
public:
virtual void Handle (Context*) {}
protected:
virtual void ChangeState (Context*, State*);
};
//// ------------------------------------------------------------------------
class ConcreteStateA : public State
{
public:
virtual void Handle(Context* c);
};
class ConcreteStateB : public State
{
public:
virtual void Handle(Context* c);
};
class ConcreteStateC : public State
{
public:
virtual void Handle(Context* c);
};
void ConcreteStateA::Handle(Context* c)
{
std::cout << "ConcreteStateA::Handle()" << std::endl;
ChangeState (c, new ConcreteStateB());
}
void ConcreteStateB::Handle(Context* c)
{
std::cout << "ConcreteStateB::Handle()" << std::endl;
ChangeState (c, new ConcreteStateC());
}
void ConcreteStateC::Handle(Context* c)
{
std::cout << "ConcreteStateC::Handle()" << std::endl;
ChangeState (c, new ConcreteStateA());
}
//// ------------------------------------------------------------------------
class Context
{
public:
friend class State;
public:
Context () : State_(0)
{
State_ = new ConcreteStateA();
}
virtual ~Context ()
{
if (State_)
delete State_;
}
public:
void Request (void)
{
if (State_)
{
State_->Handle(this);
}
}
protected:
void ChangeState (State *s)
{
if (State_)
{
delete State_;
}
State_ = s;
}
private:
State *State_;
};
//// ------------------------------------------------------------------------
void State::ChangeState (Context* c, State* s)
{
c->ChangeState (s);
}
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Context context;
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
return 0;
}
-----------------------------------------------------------------------------
ConcreteStateA::Handle()
ConcreteStateB::Handle()
ConcreteStateC::Handle()
ConcreteStateA::Handle()
ConcreteStateB::Handle()
ConcreteStateC::Handle()
-----------------------------------------------------------------------------
[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
-----------------------------------------------------------------------------
[Memento]
의도:
캡슐화를 위배하지 않으면서 객체의 내부 상태를 파악하고 표현함으로써 객체의 상태를 저장해
둔 상태로 다시 복구 할 수 있게 한다.
다른 이름:
Token
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Memento
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <deque>
#include <list>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <string>
/////////////////////////////////////////////////////////////////////////////
//
// Utility
//
/////////////////////////////////////////////////////////////////////////////
template<class T>
struct deleteobject_functor : public std::unary_function<T, void>
{
public:
void operator()(T ptr)
{
delete ptr;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Memento
//
/////////////////////////////////////////////////////////////////////////////
typedef std::string State;
class Memento
{
private:
friend class Originator;
private:
Memento(void) : State_("empty")
{
}
public:
State GetState (void) const
{
return State_;
}
void SetState (State s)
{
State_ = s;
}
private:
State State_;
};
class Originator
{
public:
Originator (void) : State_("empty")
{
}
public:
Memento* CreateMemento (void)
{
Memento *m;
m = new Memento();
m->SetState (State_);
return m;
}
void SetMemento (const Memento* m)
{
State_ = m->GetState ();
delete m;
}
void SetState (std::string s)
{
State_ = s;
}
private:
State State_;
public:
friend std::ostream& operator<< (std::ostream&, const Originator&);
};
class CareTaker
{
public:
virtual ~CareTaker ()
{
std::for_each(History_.begin(), History_.end(), deleteobject_functor<Memento*>());
}
public:
void Push (Memento* m)
{
History_.push_back (m);
}
Memento* Pop (void)
{
Memento* m = 0;
if (!History_.empty())
{
m=History_.back();
History_.pop_back();
}
return m;
}
private:
std::deque <Memento*> History_;
};
////-------------------------------------------------------------------------
std::ostream& operator<< (std::ostream& os, const Originator &org)
{
os << "Originator's State=" << org.State_.c_str();
return os;
}
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Originator originator;
CareTaker caretaker;
originator.SetState ("first");
std::cout << originator << std::endl;
std::cout << std::endl;
caretaker.Push ( originator.CreateMemento () );
originator.SetState ("second");
std::cout << originator << std::endl;
caretaker.Push ( originator.CreateMemento () );
originator.SetState ("third");
std::cout << originator << std::endl;
std::cout << std::endl;
originator.SetMemento ( caretaker.Pop () );
std::cout << originator << std::endl;
originator.SetMemento ( caretaker.Pop () );
std::cout << originator << std::endl;
return 0;
}
-----------------------------------------------------------------------------
Originator's State=first
Originator's State=second
Originator's State=third
Originator's State=second
Originator's State=first
-----------------------------------------------------------------------------
[Mediator]
의도:
객체들 간의 상호작용을 캡슐화하여 하나의 객체 안에 정의한다. Mediator 패턴은 각 객체가
관련성을 갖는 다른 객체에 대한 참조 관계를 직접 정의하기보다는 이를 독립된 다른 객체가
관리하게 한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Mediator
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Mediator
//
//
/////////////////////////////////////////////////////////////////////////////
class Colleague;
class Mediator
{
public:
virtual ~Mediator () {}
public:
virtual void OnNotify (Colleague *) {}
};
class Colleague
{
public:
Colleague (Mediator* m) : Mediator_(m) {}
virtual ~Colleague () {}
public:
virtual void Notify ()
{
if (Mediator_)
{
Mediator_->OnNotify (this);
}
}
protected:
Mediator* Mediator_;
};
////-------------------------------------------------------------------------
class ConcreteColleague1 : public Colleague
{
public:
ConcreteColleague1 (Mediator* m) : Colleague (m) {}
public:
void Act1 (void)
{
Notify ();
}
};
class ConcreteColleague2 : public Colleague
{
public:
ConcreteColleague2 (Mediator* m) : Colleague (m) {}
public:
void Act2 (void)
{
Notify ();
}
};
class ConcreteMediator : public Mediator
{
public:
void Init (void)
{
Colleague1_.reset ( new ConcreteColleague1(this) );
Colleague2_.reset ( new ConcreteColleague2(this) );
}
void Run (void)
{
Colleague1_->Act1 ();
Colleague2_->Act2 ();
}
virtual void OnNotify (Colleague *c)
{
if (c==Colleague1_.get())
{
std::cout << "ConcreteMediator::OnNotify() = Colleague1_" << std::endl;
}
else if (c==Colleague2_.get())
{
std::cout << "ConcreteMediator::OnNotify() = Colleague2_" << std::endl;
}
}
private:
std::auto_ptr<ConcreteColleague1> Colleague1_;
std::auto_ptr<ConcreteColleague2> Colleague2_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
ConcreteMediator mediator;
mediator.Init ();
mediator.Run ();
return 0;
}
-----------------------------------------------------------------------------
ConcreteMediator::OnNotify() = Colleague1_
ConcreteMediator::OnNotify() = Colleague2_
-----------------------------------------------------------------------------
[Template Method]
의도:
오퍼레이션에 알고리즘의 기본 골격 구조를 정의하고 구체적인 단계는 서브클래스에 정의한다.
Template Method 클래스의 서브클래스는 알고리즘의 구조를 변경하지 않고 알고리즘 처리
단계들을 재정의 할 수 있다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Template Method
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
/////////////////////////////////////////////////////////////////////////////
//
// Template Method
//
/////////////////////////////////////////////////////////////////////////////
class AbstractClass
{
public:
virtual ~AbstractClass()
{
}
public:
void TemplateMethod (void)
{
std::cout << "AbstractClass::TemplateMethod()" << std::endl;
std::cout << "\t";
PrimitiveOperation1();
std::cout << "\t";
PrimitiveOperation2();
std::cout << std::endl;
}
virtual void PrimitiveOperation1 (void)
{
}
virtual void PrimitiveOperation2 (void)
{
}
};
class ConcreteClassA : public AbstractClass
{
public:
virtual void PrimitiveOperation1 (void)
{
std::cout << "ConcreteClassA::PrimitiveOperation1()" << std::endl;
}
virtual void PrimitiveOperation2 (void)
{
std::cout << "ConcreteClassA::PrimitiveOperation2()" << std::endl;
}
};
class ConcreteClassB : public AbstractClass
{
public:
virtual void PrimitiveOperation1 (void)
{
std::cout << "ConcreteClassB::PrimitiveOperation1()" << std::endl;
}
virtual void PrimitiveOperation2 (void)
{
std::cout << "ConcreteClassB::PrimitiveOperation2()" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
std::auto_ptr<AbstractClass> a;
a.reset ( new ConcreteClassA() );
a->TemplateMethod ();
a.reset ( new ConcreteClassB() );
a->TemplateMethod ();
return 0;
}
-----------------------------------------------------------------------------AbstractClass::TemplateMethod()
ConcreteClassA::PrimitiveOperation1()
ConcreteClassA::PrimitiveOperation2()
AbstractClass::TemplateMethod()
ConcreteClassB::PrimitiveOperation1()
ConcreteClassB::PrimitiveOperation2()
-----------------------------------------------------------------------------
[Strategy]
의도:
다양한 알고리즘이 존재하면 이들 각각을 하나의 클래스로 캡슐화하여 알고리즘의 대체가 가능
하도록 한다. Strategy패턴을 이용하면 클라이언트와 독립적인 다양한 알고리즘으로 변형할 수
있다. 알고리즘을 바구더라도 클라이언트는 아무런 변경을 할 필요가 없다.
다른 이름:
Policy
참고:
Policy-based design이 Strategy을 이용한 디자인 방법이다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Strategy
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
/////////////////////////////////////////////////////////////////////////////
//
// Strategy
//
//
/////////////////////////////////////////////////////////////////////////////
class Strategy
{
public:
virtual ~Strategy() {}
public:
virtual void AlgorithmInterface(void) = 0;
};
template <typename Strategy>
class Context
{
public:
void operator() ()
{
Strategy_.AlgorithmInterface ();
}
private:
Strategy Strategy_;
};
class ContextByRunTime
{
public:
explicit ContextByRunTime (Strategy *s) :
Strategy_ (s)
{
}
public:
void operator() ()
{
Strategy_->AlgorithmInterface ();
}
private:
Strategy *Strategy_;
};
class ConcreteStrategyA : public Strategy
{
public:
virtual void AlgorithmInterface(void)
{
std::cout << "ConcreteStrategyA::AlgorithmInterface()" << std::endl;
}
};
class ConcreteStrategyB : public Strategy
{
public:
virtual void AlgorithmInterface(void)
{
std::cout << "ConcreteStrategyB::AlgorithmInterface()" << std::endl;
}
};
class ConcreteStrategyC : public Strategy
{
public:
virtual void AlgorithmInterface(void)
{
std::cout << "ConcreteStrategyC::AlgorithmInterface()" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
ConcreteStrategyA s1;
ConcreteStrategyB s2;
ConcreteStrategyC s3;
ContextByRunTime cr1(&s1);
ContextByRunTime cr2(&s2);
ContextByRunTime cr3(&s3);
Context<ConcreteStrategyA> cc1;
Context<ConcreteStrategyB> cc2;
Context<ConcreteStrategyC> cc3;
std::cout << "by run-time" << std::endl;
cr1();
cr2();
cr3();
std::cout << std::endl;
std::cout << "by compile-time" << std::endl;
cc1();
cc2();
cc3();
return 0;
}
-----------------------------------------------------------------------------
by run-time
ConcreteStrategyA::AlgorithmInterface()
ConcreteStrategyB::AlgorithmInterface()
ConcreteStrategyC::AlgorithmInterface()
by compile-time
ConcreteStrategyA::AlgorithmInterface()
ConcreteStrategyB::AlgorithmInterface()
ConcreteStrategyC::AlgorithmInterface()
-----------------------------------------------------------------------------
[Chain Of Responsibility]
의도:
메시지를 보내는 객체와 이를 받아 처리하는 객체들 간의 결합도를 없애기 위한 패턴이다.
하나의 요청에 대한 처리가 반드시 한 객체에서만 이루어지지 않고, 여러 객체에게 그 처리의
기회를 주려는 것이다. 즉, 이 패턴에서는 하나의 서비스 처리를 여러 객체에 나눌 수 있도록
한다. 메시지를 수신하여 처리를 담당할 객체들을 하나의 연결 고리로 만들고, 실제로 요청을
처리하는 객체를 만날 때까지 계속해서 요청을 전달하게 한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Chain Of Responsibility
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <memory>
#include <iostream>
#include <deque>
#include <list>
#include <vector>
#include <algorithm>
#include <iomanip>
/////////////////////////////////////////////////////////////////////////////
//
// Chain Of Responsibility
//
//
/////////////////////////////////////////////////////////////////////////////
class Handler
{
public:
typedef int Topic;
public:
explicit Handler (Handler *s=0, Topic t=0) :
Successor_(s),
Topic_ (t)
{
}
virtual ~Handler ()
{
}
public:
virtual void HandleRequest(void)
{
if (Successor_)
{
Successor_->HandleRequest ();
}
else
{
std::cout << "Handler::HandleRequest() : no Successor_" << std::endl;
}
}
virtual void SetHandler (Handler *s=0, Topic t=0)
{
Successor_=s;
Topic_ =t;
}
protected:
Handler* Successor_;
Topic Topic_;
};
class ConcreteHandler1 : public Handler
{
public:
ConcreteHandler1 (Handler *s=0, Topic t=0) :
Handler(s,t)
{
}
public:
virtual void HandleRequest(void)
{
if (Topic_==1)
{
std::cout << "ConcreteHandler1::HandleRequest()" << std::endl;
}
else
{
Handler::HandleRequest();
}
};
};
class ConcreteHandler2 : public Handler
{
public:
ConcreteHandler2 (Handler *s=0, Topic t=0) :
Handler(s,t)
{
}
public:
virtual void HandleRequest(void)
{
if (Topic_==2)
{
std::cout << "ConcreteHandler2::HandleRequest()" << std::endl;
}
else
{
Handler::HandleRequest();
}
};
};
class ConcreteChildHandler : public ConcreteHandler2
{
public:
ConcreteChildHandler (Handler *s=0, Topic t=0) :
ConcreteHandler2(s,t)
{
}
public:
virtual void HandleRequest(void)
{
if (Topic_==3)
{
std::cout << "ConcreteChildHandler::HandleRequest()" << std::endl;
}
else
{
ConcreteHandler2::HandleRequest();
}
};
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Handler* handler1 = new Handler ();
Handler* handler2 = new ConcreteHandler1 (handler1, 1);
Handler* handler3 = new ConcreteHandler2 (handler2, 1);
Handler* handler4 = new ConcreteChildHandler (handler3, 2);
Handler* handler5 = new ConcreteChildHandler (handler3, 3);
handler1->HandleRequest();
handler2->HandleRequest();
handler3->HandleRequest();
handler4->HandleRequest();
handler5->HandleRequest();
delete handler1;
delete handler2;
delete handler3;
delete handler4;
delete handler5;
return 0;
}
-----------------------------------------------------------------------------Handler::HandleRequest() : no Successor_
ConcreteHandler1::HandleRequest()
ConcreteHandler1::HandleRequest()
ConcreteHandler2::HandleRequest()
ConcreteChildHandler::HandleRequest()
-----------------------------------------------------------------------------
[Command]
의도:
요청 자체를 객체화하는 것이다. 그리고 서로 다른 요청을 객체화하여 클라이언트에게
파라미터로 넘겨줄 수 있게한다.
다른이름:
Action, Transaction
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Command
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <deque>
#include <list>
#include <vector>
#include <algorithm>
#include <iomanip>
/////////////////////////////////////////////////////////////////////////////
//
// Command
//
//
/////////////////////////////////////////////////////////////////////////////
class Command
{
protected:
Command () {}
public:
virtual ~Command () {}
public:
virtual void Execute (void) = 0;
virtual void Unexecute (void) {}
};
/////////////////////////////////////////////////////////////////////////////
//
// Utility
//
/////////////////////////////////////////////////////////////////////////////
template<class T>
struct deleteobject_functor : public std::unary_function<T, void>
{
public:
void operator()(T ptr)
{
delete ptr;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Application
//
//
/////////////////////////////////////////////////////////////////////////////
class Receiver
{
public:
void Print_A (int a)
{
std::cout << "Receiver::Print_A(" << a << ")" << std::endl;
}
void Print_B (const char *b)
{
std::cout << "Receiver::Print_B(" << b << ")" << std::endl;
}
void Print_C (void)
{
std::cout << "Receiver::Print_C()" << std::endl;
}
void Print_D (void)
{
std::cout << "Receiver::Print_D()" << std::endl;
}
};
////-------------------------------------------------------------------------
//// Commands
////-------------------------------------------------------------------------
template <typename Receiver>
class SimpleCommand : public Command
{
public:
typedef void (Receiver::*Action)(void);
public:
SimpleCommand (Receiver *receiver, Action action) :
Receiver_ (receiver),
Action_ (action)
{
}
public:
virtual void Execute (void)
{
(Receiver_->*Action_) ();
}
private:
Receiver *Receiver_;
Action Action_;
};
class ConcreteACommand : public Command
{
public:
ConcreteACommand (Receiver *receiver, int param) :
Receiver_ (receiver),
Param_ (param)
{
}
public:
virtual void Execute (void)
{
Receiver_->Print_A (Param_);
}
private:
Receiver *Receiver_;
int Param_;
};
class ConcreteBCommand : public Command
{
public:
ConcreteBCommand (Receiver *receiver, std::string param) :
Receiver_ (receiver),
Param_ (param)
{
}
public:
virtual void Execute (void)
{
Receiver_->Print_B (Param_.c_str());
}
private:
Receiver *Receiver_;
std::string Param_;
};
class MacroCommand : public Command
{
public:
virtual ~MacroCommand ()
{
std::for_each (Commands_.begin(), Commands_.end(), deleteobject_functor<Command*>());
}
protected:
static void ExecuteCommand (Command* cmd)
{
cmd->Execute();
}
public:
void Add (Command* cmd)
{
Commands_.push_back (cmd);
}
virtual void Execute (void)
{
std::for_each (Commands_.begin(), Commands_.end(), ExecuteCommand);
}
private:
std::list<Command*> Commands_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Receiver receiver;
MacroCommand macrocmd;
macrocmd.Add (new ConcreteACommand (&receiver, 100));
macrocmd.Add (new ConcreteBCommand (&receiver, "Hello World!"));
macrocmd.Add (new SimpleCommand<Receiver> (&receiver, &Receiver::Print_C));
macrocmd.Add (new SimpleCommand<Receiver> (&receiver, &Receiver::Print_D));
macrocmd.Execute();
return 0;
}
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
Compoiste 객체를 Visitor가 순회할때 자식 객체들은 Accept를 재귀호출하고 자신은 Visit를
수행하는 방법으로 순회 한다.
--------------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>
#include <list>
#include <string>
#include <algorithm>
#include <iostream>
#include <deque>
/////////////////////////////////////////////////////////////////////////////
//
// Base Patterns
//
//
/////////////////////////////////////////////////////////////////////////////
//// ------------------------------------------------------------------------
//// Visitor Pattern
//// ------------------------------------------------------------------------
class Visitable;
class Visitor
{
protected:
Visitor() {}
public:
virtual void Visit (Visitable *) {}
};
class Visitable
{
protected:
Visitable() {}
public:
virtual void Accept (Visitor &v)
{
v.Visit (this);
}
};
class VisitableObjectAcceptor
{
protected:
Visitor &Visitor_;
public:
explicit VisitableObjectAcceptor (Visitor &v) : Visitor_(v)
{
}
public:
void operator () (Visitable* o)
{
if (o)
{
o->Accept (Visitor_);
}
}
};
//// ------------------------------------------------------------------------
//// Composite Pattern
//// ------------------------------------------------------------------------
class Composite;
class Component : public Visitable
{
public:
virtual Composite* GetComposite (void)
{
return 0;
}
virtual void Add (Component* c) {};
virtual void Remove(Component* c) {};
};
class Composite : public Component
{
protected:
Composite () {}
public:
virtual Composite* GetComposite (void)
{
return this;
}
public:
virtual void Add (Component* c)
{
components_.push_back (c);
};
virtual void Remove(Component* c)
{
components_.remove (c);
};
virtual void Accept (Visitor &v)
{
v.Visit (this);
std::for_each(components_.begin(), components_.end(), VisitableObjectAcceptor(v));
}
protected:
std::list <Component*> components_;
};
class Leaf : public Component
{
};
/////////////////////////////////////////////////////////////////////////////
//
// Application
//
//
/////////////////////////////////////////////////////////////////////////////
//// ------------------------------------------------------------------------
//// Composite
//// ------------------------------------------------------------------------
class Directory : public Composite
{
public:
Directory (const std::string name) : name_ (name)
{
}
public:
virtual std::string GetName (void) const { return name_; }
virtual size_t GetFileCount (void) const { return components_.size(); }
protected:
std::string name_;
};
class File : public Leaf
{
public:
File (const std::string name, int size=0) : name_ (name), size_(size)
{
}
public:
virtual int GetSize (void) const { return size_; }
virtual std::string GetName (void) const { return name_; }
protected:
std::string name_;
int size_;
};
class Mp3File : public File
{
public:
Mp3File (const std::string filename) : File (filename, 1000) {}
};
class TxtFile : public File
{
public:
TxtFile (const std::string filename) : File (filename, 10) {}
};
//// ------------------------------------------------------------------------
//// Vistor
//// ------------------------------------------------------------------------
class Enumerator: public Visitor
{
public:
Enumerator ()
{
}
public:
virtual void Visit (Visitable *o)
{
File *file=dynamic_cast<File*> (o);
Directory *dir =dynamic_cast<Directory*> (o);
if (file) std::cout << "\"" << file->GetName() << "\"" << std::endl;
if (dir ) std::cout << "[" << dir ->GetName() << "]" << std::endl;
}
};
class CalcTotalSize : public Visitor
{
public:
CalcTotalSize () : m_TotalSize(0)
{
}
public:
virtual void Visit (Visitable *o)
{
File *file=dynamic_cast<File*> (o);
if (file)
{
m_TotalSize+=file->GetSize();
}
}
public:
int GetTotalSize (void) { return m_TotalSize; }
private:
int m_TotalSize;
};
/////////////////////////////////////////////////////////////////////////////
//
// Start up
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain (int argc, _TCHAR* argv[])
{
Directory dir_root ("RootDirectory");
Directory dir_sub1 ("SubDirectory1");
Directory dir_sub2 ("SubDirectory2");
Mp3File file_mp3_1 ("a.mp3");
Mp3File file_mp3_2 ("b.mp3");
TxtFile file_txt_1 ("a.txt");
TxtFile file_txt_2 ("b.txt");
dir_sub1.Add (&file_mp3_1);
dir_sub1.Add (&file_mp3_2);
dir_sub2.Add (&file_mp3_1);
dir_sub2.Add (&file_txt_1);
dir_root.Add (&dir_sub1);
dir_root.Add (&dir_sub2);
dir_root.Add (&file_txt_1);
dir_root.Add (&file_txt_2);
CalcTotalSize calc_size;
dir_root.Accept (calc_size);
std::cout << "# CalcTotalSize::GetTotalSize()=" << calc_size.GetTotalSize() << std::endl;
std::cout << std::endl;
std::cout << "# Enumerator" << std::endl;
Enumerator show_enum;
dir_root.Accept (show_enum);
return 0;
}
--------------------------------------------------------------------------------
# CalcTotalSize::GetTotalSize()=3030
# Enumerator
[RootDirectory]
[SubDirectory1]
"a.mp3"
"b.mp3"
[SubDirectory2]
"a.mp3"
"a.txt"
"a.txt"
"b.txt"
-----------------------------------------------------------------------------
[Composite]
의도:
부분-전체 계층을 나타내기 위핸 복합 객체를 트리 구조로 만든다.
Composite 패턴은 클라이언트가 개별적 객체와 복합 객체 모두를 동일하게 다루도록
한다.
설명:
순환구조일때 즉, Compoiste구조에서 A와 B가 있을때 A는 B를 Child 객체로 소유하고, 또한
B가 A를 Child로 소유하고 있을 경우 A와 B가 Handle로 구현되어있는 경우 서로 Reference-
Counting으로 관계가 있기 때문에 Memory Leak이 생길 수 있다. 이를 해결하기 위해서는
Gabege-collector를 구현해야 하는데, 그냥 Handle로 안하는 것이 정신 건강에 이롭다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Composite
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <list>
#include <string>
#include <algorithm>
#include <iostream>
#include <deque>
/////////////////////////////////////////////////////////////////////////////
//
// Composite
//
/////////////////////////////////////////////////////////////////////////////
class Composite;
class Component
{
public:
explicit Component (const std::string name) : name_ (name)
{
}
public:
virtual Composite* GetComposite (void)
{
return 0;
}
virtual void Add (Component* c) {};
virtual void Remove(Component* c) {};
public:
virtual std::string GetName (void) const { return name_; }
protected:
std::string name_;
};
class Composite : public Component
{
public:
explicit Composite (const std::string name) : Component(name) {}
public:
virtual Composite* GetComposite (void)
{
return this;
}
public:
virtual void Add (Component* c)
{
components_.push_back (c);
};
virtual void Remove(Component* c)
{
components_.remove (c);
};
virtual std::list<Component*>* GetChilds (void)
{
return &components_;
}
protected:
std::list <Component*> components_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
void ShowComposite (Composite* composite, int indent)
{
int i;
for (i=0; i<indent; i++)
std::cout << " ";
std::cout << "[" << composite->GetName() << "]" << std::endl;
std::list <Component*>::iterator child;
indent++;
for (child=composite->GetChilds()->begin();
child!=composite->GetChilds()->end();
child++)
{
if (0==(*child)->GetComposite())
{
for (i=0; i<indent; i++)
std::cout << " ";
std::cout << (*child)->GetName() << std::endl;
}
else
{
ShowComposite ((*child)->GetComposite(), indent);
}
}
indent--;
}
int _tmain (int argc, _TCHAR* argv[])
{
Composite Root ("Root");
Composite Sub1 ("Sub1");
Composite Sub2 ("Sub2");
Component Item1("Item1");
Component Item2("Item2");
Component Item3("Item3");
Component Item4("Item4");
Component Item5("Item5");
Root.Add (&Sub1);
Root.Add (&Sub2);
Root.Add (&Item1);
Sub1.Add (&Item2);
Sub1.Add (&Item3);
Sub2.Add (&Item4);
Sub2.Add (&Item5);
ShowComposite (&Root, 0);
return 0;
}
-----------------------------------------------------------------------------
[Visitor]
의도:
객체 구조의 요소들에 수행할 오퍼레이션을 표한한 패턴이다. Visitor 패턴은
오퍼레이션이 처리할 요소의 클래스를 변경하지 않고도 새로운 오퍼레이션을
정의 할 수 있게한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Behavioral part of GoF's Design Patterns
//
// - Visitor
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <list>
class ElementA;
class ElementB;
class CompoisteElement;
/////////////////////////////////////////////////////////////////////////////
//
// Visitor base
//
/////////////////////////////////////////////////////////////////////////////
class Visitor
{
protected:
Visitor();
public:
virtual ~Visitor();
public:
virtual void VisitElementA (ElementA *);
virtual void VisitElementB (ElementB *);
virtual void VisitCompoistElement(CompoisteElement *);
};
Visitor::Visitor() {}
Visitor::~Visitor() {}
void Visitor::VisitElementA (ElementA *)
{
std::cout << "Visitor::VisitElementA (ElementA *)" << std::endl;
}
void Visitor::VisitElementB (ElementB *)
{
std::cout << "Visitor::VisitElementB (ElementA *)" << std::endl;
}
void Visitor::VisitCompoistElement(CompoisteElement *)
{
std::cout << "Visitor::VisitCompoistElement (ElementA *)" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Element base
//
/////////////////////////////////////////////////////////////////////////////
class Element
{
protected:
Element ();
public:
virtual ~Element ();
public:
virtual void Accept (Visitor &) = 0;
};
Element::Element () {};
Element::~Element () {};
/////////////////////////////////////////////////////////////////////////////
//
// Elements
//
/////////////////////////////////////////////////////////////////////////////
class ElementA : public Element
{
public:
virtual void Accept (Visitor &v)
{
v.VisitElementA (this);
}
};
class ElementB : public Element
{
public:
virtual void Accept (Visitor &v)
{
v.VisitElementB (this);
}
};
class CompoisteElement : public Element
{
public:
virtual void Accept (Visitor &v)
{
std::list<Element*>::iterator i;
for (i=childs_.begin(); i!=childs_.end(); i++)
{
(*i)->Accept (v);
}
v.VisitCompoistElement (this);
}
public:
std::list<Element*> childs_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Visitors
//
/////////////////////////////////////////////////////////////////////////////
class VisitorA : public Visitor
{
public:
virtual void VisitElementA (ElementA *)
{
std::cout << "VisitorA::VisitElementA (ElementA *)" << std::endl;
}
virtual void VisitElementB (ElementB *)
{
std::cout << "VisitorA::VisitElementB (ElementB *)" << std::endl;
}
virtual void VisitCompoistElement(CompoisteElement *)
{
std::cout << "VisitorA::VisitCompoistElement (CompoisteElement *)" << std::endl;
}
};
class VisitorB : public Visitor
{
public:
virtual void VisitElementA (ElementA *)
{
std::cout << "VisitorB::VisitElementA (ElementA *)" << std::endl;
}
virtual void VisitElementB (ElementB *)
{
std::cout << "VisitorB::VisitElementB (ElementB *)" << std::endl;
}
virtual void VisitCompoistElement(CompoisteElement *)
{
std::cout << "VisitorB::VisitCompoistElement (CompoisteElement *)" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
ElementA element_a;
ElementB element_b;
CompoisteElement c_element;
c_element.childs_.push_back (&element_a);
c_element.childs_.push_back (&element_b);
VisitorA visitor_a;
VisitorB visitor_b;
element_a.Accept (visitor_a);
element_b.Accept (visitor_a);
c_element.Accept (visitor_a);
std::cout << std::endl;
element_a.Accept (visitor_b);
element_b.Accept (visitor_b);
c_element.Accept (visitor_b);
std::cout << std::endl;
std::cout << std::endl;
std::cout << std::endl;
Element *e;
std::cout << "by element_a" << std::endl;
e = &element_a;
e->Accept (visitor_a);
e->Accept (visitor_b);
std::cout << std::endl;
std::cout << "by element_b" << std::endl;
e = &element_b;
e->Accept (visitor_a);
e->Accept (visitor_b);
std::cout << std::endl;
std::cout << "by c_element" << std::endl;
e = &c_element;
e->Accept (visitor_a);
e->Accept (visitor_b);
return 0;
}
VisitorB::VisitElementA (ElementA *)
VisitorB::VisitElementB (ElementB *)
VisitorB::VisitElementA (ElementA *)
VisitorB::VisitElementB (ElementB *)
VisitorB::VisitCompoistElement (CompoisteElement *)
by element_a
VisitorA::VisitElementA (ElementA *)
VisitorB::VisitElementA (ElementA *)
by element_b
VisitorA::VisitElementB (ElementB *)
VisitorB::VisitElementB (ElementB *)
by c_element
VisitorA::VisitElementA (ElementA *)
VisitorA::VisitElementB (ElementB *)
VisitorA::VisitCompoistElement (CompoisteElement *)
VisitorB::VisitElementA (ElementA *)
VisitorB::VisitElementB (ElementB *)
VisitorB::VisitCompoistElement (CompoisteElement *)