Post List

레이블이 DesignPattern인 게시물을 표시합니다. 모든 게시물 표시
레이블이 DesignPattern인 게시물을 표시합니다. 모든 게시물 표시

2015년 1월 4일 일요일

1부 생성 패턴들

생​성 패턴들

1. 추상 팩토리 패턴 Abstract Factory Pattern

  호환성 있는 개체군을 하나의 팩토리 개체를 통해 생성하게 함으로써 사용자 편의성을 증대시킬 수 있다.

2. 빌더 패턴 Builder Pattern

 개체를 생성하는 과정이 복잡하면 생성하는 알고리즘을 블더에 구현하여 빌더 개체를 통해 복잡한 개체 생성을 쉽게 사용할 수 있다.

3. 팩토리 메서드 패턴 (Factory Method Pattern)

 생성할 개체의 형태가 정형화 되어 있지 않을 때 생성할 개체에 대한 구체적인 형태를 서브 클래스에서 정의할 때 사용된다.

4. 원형 패턴 (Prototype Pattern)

 단순히 멤버 필드의 초기값이나 한계값에 차이가 있는 파생 클래스가 너무 많이질 수 있다면 견본 개체를 여러 개를 두고 견복 개체를 통해 원하는 형태의 개체를 생성함으로써 복잡한 패생 클래스를 만들지 않게 도와준다.

5. 단일체 패턴 (Singleton Pattern)




 프로그램내부에 특정 클래스 형식의 인스턴스가 하나만 (또는 N개 이하) 존재하게 하여 여러 곳에서 같은 개체에 접근하고자 할 때 사용된다.

Singleton Pattern (단일체 패턴)

Singleton Pattern

 프로그램상에 특정 형식의 개체가 N개 이하로만 생성됨을 보장해주는 방법 (보통 N은 1개일 경우가 많다.)

유용한 경우

1. 어떤 클래스의 객체가 최대 N개 이하로만 존재해야 할 때 이를 관리하기에 유용하다. 특히 N은 1일 경우가 많다.
2. 상속 관계에 놓인 클래스들에 대해 적제적으로 생성되는 객체의 최대 개수를 제한하고자 할 때 유용하다. 

장점

 1. 전역 변수 방식은 최대 N개 이하의 객체만 생성되어 존재한다는 사실을 확실히 보장할 수 없다. 특히 여러 사람이 공동 작업을 하는 경우에는 이런 문제가 발생될 소지가 크다. 반면 싱글턴 패턴 방식은 클래스 차원에서 최대 N개 까지만 객체가 생성되게 보장 해주기 때문에 이와 같은 문제는 걱정할 필요가 없다.
2. 전역 변수 방식으로 객체를 생성하기 위해서는 처음부터 객체를 초기화 시키기 위한 충분한 정보를 알고 있어야 한다. 반면 Singleton 패턴의 경우에는 CreateInstance() 클래스 멤버함수가 불려질 때까지는 객체가 생성되지 않으므로 처음부터 객체를 생성하기 위해 모든 정보를 알 필요가 없다.

통상적으로 N이 1개일 경우의 Singleton의 예제는 많고 그 사용법 또한 쉽다. 예전에 써놓은 예제 3가지는 아래 링크를 참조하기 바란다.

Singleton 예제 (Java)

Singleton과 일반 Instance 둘 다 지원되는 Class (C#)

C++ Singleton 을 지원하는 Template Class

 이번에는 조금 다른 예제를 하나 소개하고자 한다. 스타크래프트 게임에서 각 종족별로 Unit 수가 200개 이하로 제한되어 있다. 각 유닛별로 보급창 밥통의 요구하는 개수또한 다르다. 이것을 Singleton 을 이용하여 구현하면 유닛수 제한을 비교적 효율적으로 재밌게 구현이 가능하다. Singleton Class로 unit을 구현한 뒤 200개의 개체제한을 설정하고 생성되는 개체를 List로 관리한다.


#include "stdafx.h"
#include <iostream>
#include <windows.h>
 
class unit{
public:
    virtual int getUseCount() const = 0;
    static const int maxUnitCount = 200;
    static unit* CreateInstance()
    {
        return 0;
    }
    static void init()
    {
        unitcount = 0;
        memset(pUnit, 0x00, (sizeof(unit*) * unit::maxUnitCount));
    }
 
    static void DestroyUnit(unit* p)
    {
        for(int i = 0; i < unit::maxUnitCount; i++)
        {
            if(unit::pUnit[i] == p)
            {
                unit::unitcount -= p->getUseCount();
                std::cout << "Unit Count : " << unit::unitcount << std::endl;
                Sleep(300);
                if(unit::unitcount < 0) unit::unitcount = 0;
                delete p;
                unit::pUnit[i] = NULL;
                return ;
            }
        }
    }
 
    static void DestroyAllUnit()
    {
        for(int i = 0; i < unit::maxUnitCount; i++)
        {
            if(unit::pUnit[i])
            {
                unit::unitcount -= pUnit[i]->getUseCount();
                std::cout << "Unit Count : " << unit::unitcount << std::endl;
                Sleep(300);
                if(unit::unitcount < 0) unit::unitcount = 0;
                delete pUnit[i];
                unit::pUnit[i] = NULL;
            }
        }       
    }
 
protected:
    unit(){}
    unit(const unit& rhs){}
    static int unitcount;
    static unit* pUnit[unit::maxUnitCount];
};
 
unit*   unit::pUnit[unit::maxUnitCount];
int     unit::unitcount;
 
class marine : public unit
{
public:
    int getUseCount() const
    {
        return marine::useUnitCount;
    }
    static const int useUnitCount = 1;
    static unit* CreateInstance(){
        if(marine::useUnitCount + unit::unitcount > unit::maxUnitCount)
        {
            std::cout << "Want : " << marine::useUnitCount << " Now : " << unit::unitcount << std::endl;
            Sleep(300);
            return NULL;
        }
        else
        {
            unit::unitcount += marine::useUnitCount;
            std::cout << "Unit Count : " << unit::unitcount << std::endl;
            Sleep(300);
            for(int i = 0; i < unit::maxUnitCount; i++)
            {
                if(unit::pUnit[i] == NULL)
                {
                    unit::pUnit[i] = new marine;
                    return unit::pUnit[i];
                }
            }
        }
        return NULL;
    }
protected:
    marine(){}
    marine(const marine& rhs){}
};
 
class tank : public unit
{
public:
    int getUseCount() const
    {
        return tank::useUnitCount;
    }
    static const int useUnitCount = 2;
    static unit* CreateInstance(){
        if(tank::useUnitCount + unit::unitcount > unit::maxUnitCount)
        {
            std::cout << "Want : " << tank::useUnitCount << " Now : " << unit::unitcount << std::endl;
            Sleep(300);
            return NULL;
        }
        else
        {
            unit::unitcount += tank::useUnitCount;
            std::cout << "Unit Count : " << unit::unitcount << std::endl;
            Sleep(300);
            for(int i = 0; i < unit::maxUnitCount; i++)
            {
                if(unit::pUnit[i] == NULL)
                {
                    unit::pUnit[i] = new tank;
                    return unit::pUnit[i];
                }
            }
        }
        return NULL;    
    }
protected:
    tank(){}
    tank(const tank& rhs){}
};
 
class battlecruiser : public unit
{
public:
    int getUseCount() const
    {
        return battlecruiser::useUnitCount;
    }
    static const int useUnitCount = 8;
    static unit* CreateInstance(){
        if(battlecruiser::useUnitCount + unit::unitcount > unit::maxUnitCount)
        {
            std::cout << "Want : " << battlecruiser::useUnitCount << " Now : " << unit::unitcount << std::endl;
            Sleep(300);
            return NULL;
        }
        else
        {
            unit::unitcount += battlecruiser::useUnitCount;
            std::cout << "Unit Count : " << unit::unitcount << std::endl;
            Sleep(300);
            for(int i = 0; i < unit::maxUnitCount; i++)
            {
                if(unit::pUnit[i] == NULL)
                {
                    unit::pUnit[i] = new battlecruiser;
                    return unit::pUnit[i];
                }
            }
        }
        return NULL;        
    }
protected:
    battlecruiser(){}
    battlecruiser(const battlecruiser& rhs){}
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    const int testloop = 210;
 
    unit::init();
    int i;
    std::cout << "Create Marine" << std::endl;
    for(i = 0; i < testloop; i++)
    {
        marine::CreateInstance();
    }
    unit::DestroyAllUnit();
 
    std::cout << "Create tank" << std::endl;
    for(i = 0; i < testloop; i++)
    {
        tank::CreateInstance();
    }
    unit::DestroyAllUnit();
 
    std::cout << "Create battlecruiser" << std::endl;
    for(i = 0; i < testloop; i++)
    {
        battlecruiser::CreateInstance();
    }
    unit::DestroyAllUnit();
 
    return 0;
}

참조 : http://devsw.tistory.com



Prototype Pattern (원형 패턴)

Prototype Pattern

 미리 만들어진 개체(Object)를 복사하여 개체를 생성

유용한 경우

- 일반화 관계로 표현할 때 파생 클래스의 개수가 과도히 많아지고 각 클래스의 메서드에서 수행하는 알고리즘에 차이가 없으면서 생성 시에 개체의 속성 값만 다를 경우

장점

 1. 다수의 객체 생성시 발생하는 비용을 효과적으로 줄일 수 있다.
 2. 별도의 Factory나 Builder 등의 클래스 구현이 필요 없다.
 3. 실행 시간(Run-time)에도 생성할 개체의 종류를 추가/삭제가 가능하다.

단점

- Clone 함수를 구현해야 한다.

//------------------------------------------------------------------
// Prototype 인터페이스 클래스
class Prototype
{
public:
  virtual Prototype* Clone() = 0;
};
 
//------------------------------------------------------------------
// ConcretePrototype1 클래스
class ConcretePrototype1 : public Prototype
{
public:
  ConcretePrototype1() {}
  ConcretePrototype1(const ConcretePrototype1& p) {}
public:
  Prototype* Clone() override final
  {
    return new ConcretePrototype1(*this);
  }
};
 
//------------------------------------------------------------------
// ConcretePrototype2 클래스
class ConcretePrototype2 : public Prototype
{
public:
  ConcretePrototype2() {}
  ConcretePrototype2(const ConcretePrototype2& p) {}
public:
  Prototype* Clone() override final
  {
    return new ConcretePrototype2(*this);
  }
};
 
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
  Prototype* pOriginal = new ConcretePrototype1();
  Prototype* pClone = pOriginal->Clone();
   
  delete pClone;
  delete pOriginal;
 
  return 0;
}

Builder Pattern (빌더 패턴)

Builder Pattern

유용한 경우

1. 각각의 Part 로 이루어진 Object 생성시, 각 Part들의 생성들을 조합하여 Object의 생성을 가능하게하며, Part와 Object이 생성을 독립적으로 이룰 경우
2. 같은 종류의 Part들을 가지는 각각의 다른 Object 들을 동일한 방식으로 생성하고 싶을 때

장점

1. Builder 클래스는 Director클래스에게 객체를 생성할 수 있도록 인터페이스를 제공한다. 단, 생성 내부 방법은 숨긴다. Builder패턴에서 생성되는 객체의 내부구조가 바뀌더라도 기존 소스코드에 영향에 주지 않으며 새로운 하위 클래스를 생성하면 된다.
2. 객체를 생성하는 부분과 그것을 실제 표현하고 구성하는 부분을 분리 시켜줌으로써 서로간의 독립성을 기여할 수 있다.
3. 객체를 한꺼번에 생성하는 것이 아니라 부분부분 생성 후 최종 결과를 얻어가는 방식이므로 객체 생성과정을 상세히 지켜볼 수 있다.

단점

1. 객체 생성을 추가하는 것은 쉬우나 객체를 구성하는 각 부분들을 새롭게 추가하는 것은 어렵다.
2.  생성되는 객체의 구성들을 명확히 하여 추가하거나 수정해야하는 부분이 없어야 한다.

 게임 케릭터는 모두 머리, 몸, 팔, 다리, 꼬리 로 이루어져있으며, 몬스터 와 로봇 2가지 케릭터가 있는 경우. 게임 케릭터 생성을 관리하는 Director 가 있다. Director 생성시 몬스터 Builder를 이용하여 생성하면 Director는 몬스터가 생성되며, 로봇 Builder를 이용하여 만들어진 Director로 케릭터를 생성하면 로봇이 만들어진다. 위의 내용을 Code로 옮기면 아래와 같다.



#include "stdafx.h"
#include <iostream>
 
class CharacterDirector;
class Character;
class CharacterBuilder;
class RobotBuilder;
class MonsterBuilder;
 
// 캐릭터를 만드는 빌더
class CharacterBuilder {
public:
    virtual void makeCharacter() = 0;
    virtual void makeHead() = 0;
    virtual void makeBody() = 0;
    virtual void makeLegs() = 0;
    virtual void makeArms() = 0;
    virtual void makeTail() = 0;
    virtual Character* getResult() = 0;
};
 
// 캐릭터를 만들어줄 Director
class CharacterDirector {
public:
    CharacterBuilder* builder;
    CharacterDirector(CharacterBuilder* _builder):builder(_builder){}
    ~CharacterDirector(){
        if(builder)
        {
            delete builder;
            builder = NULL;
        }
    }
    Character* constructCharacter()
    {
        builder->makeCharacter();
        builder->makeHead();
        builder->makeBody();
        builder->makeArms();
        builder->makeLegs();
        builder->makeTail();
        return builder->getResult();
    }
};
 
// 캐릭터
class Character{
public:
    enum{
        robotHeadS = 0,     robotHeadM = 1,     robotHeadL = 2,
        robotBodyS = 3,     robotBodyM = 4,     robotBodyL = 5,
        robotLegsS = 6,     robotLegsM = 7,     robotLegsL = 8,
        robotArmsS = 9,     robotArmsM = 10,    robotArmsL = 11,
        robotTailS = 12,    robotTailM = 13,    robotTailL = 14,
        monsterHeadS = 15,  monsterHeadM = 16,  monsterHeadL = 17,
        monsterBodyS = 18,  monsterBodyM = 19,  monsterBodyL = 20,
        monsterLegsS = 21,  monsterLegsM = 22,  monsterLegsL = 23,
        monsterArmsS = 24,  monsterArmsM = 25,  monsterArmsL = 26,
        monsterTailS = 27,  monsterTailM = 28,  monsterTailL = 29,
    };
    int partHead;
    int partBody;
    int partLegs;
    int partArms;
    int partTail;
};
 
// 로봇 캐릭터를 만들어줄 빌더
class RobotBuilder : public CharacterBuilder{
public:
    Character* ch;
    Character* getResult(){return ch;}
    void makeCharacter(){ ch = new Character; }
    void makeHead(){ std::cout << "Make Robot Head\n"; }
    void makeBody(){ std::cout << "Make Robot Body\n"; }
    void makeLegs(){ std::cout << "Make Robot Legs\n"; }
    void makeArms(){ std::cout << "Make Robot Arms\n"; }
    void makeTail(){ std::cout << "Make Robot Tail\n"; }
};
 
// 몬스터 캐릭터를 만들어줄 빌더
class MonsterBuilder : public CharacterBuilder{
public:
    Character* ch;
    Character* getResult(){return ch;}
    void makeCharacter(){ ch = new Character; }
    void makeHead(){ std::cout << "Make Monster Head\n"; }
    void makeBody(){ std::cout << "Make Monster Body\n"; }
    void makeLegs(){ std::cout << "Make Monster Legs\n"; }
    void makeArms(){ std::cout << "Make Monster Arms\n"; }
    void makeTail(){ std::cout << "Make Monster Tail\n"; }
 
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    Character* monster;
    CharacterDirector* director = new CharacterDirector(new MonsterBuilder);
    monster = director->constructCharacter();
    delete director;
    director = NULL;
 
    Character* robot;
    director = new CharacterDirector(new RobotBuilder);
    robot = director->constructCharacter();
    delete director;
    director = NULL;
}




참조 : http://devsw.tistory.com

Abstract Factory Pattern (추상 팩토리 패턴)

Abstract Factory Pattern

유용한 경우
1. 객체 생성 방법을 한 곳에서 독립적으로 관리하고자 할 때
2. 여러 제품군 중 사용할 제품군을 쉽게 선택할 수 있도록 만들고 싶을 때.
3. 관련된 제품들이 Group이 존재하고, 각 Group별로 제품들의 종류가 가을 때
4. 제품들에 대한 클래스 라이브러리를 만들어야 하는데, 그 인터페이스만 드러내고 구현은 숨기고 싶을 때.

장점
1. 객체 생성 코드가 한곳에 있다.
2. 제품군의 교체가 쉽다.

단점
1. 제품군의 개수가 늘어날 수록 Concrete Factory 클래스의 개수도 늘어나야 한다.
2. 제품군에 새로운 제품이 추가되어야 할 경우 모든 Factory 클래스를 수정하여야 한다.

 예를 들어서 UI 들을 모아놓은 Library를 개발해야하다. UI에는 Button 과 Scrollbar가 있고, 디자인 테마로는 Rectangle과 Circle 이 있다. 테마별로 UI들의 모양이 바뀌기 때문에 RectngleButton 과 CircleScrollbar가 같이 사용되는 경우는 절대 없다. 이 것을 간단히 Abstract Factory Method를 이용하여 구현하면 아래와 같다.




//------------------------------------------------------------------
// 버튼 인터페이스
class IButton
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 스크롤 인터페이스
class IScroll
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 사각 버튼 클래스
class CButtonRectangle : public IButton
{
public:
  void print() override { cout << "CButton Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 사각 스크롤 클래스
class CScrollRectangle : public IScroll
{
public:
  void print() override { cout << "CScroll Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 버튼 클래스
class CButtonCircle : public IButton
{
public:
  void print() override { cout << "CButton Circle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 스크롤 클래스
class CScrollCircle : public IScroll
{
public:
  void print() override { cout << "CScroll Circle" << endl; }
};
 
//------------------------------------------------------------------
// 팩토리 인터페이스
class IUIFactory
{
public:
  virtual IButton* createButton() = 0;
  virtual IScroll* createScroll() = 0;
};
 
//------------------------------------------------------------------
// 사각형 팩토리 클래스
class CUIFactory_Rectangle : public IUIFactory
{
public:
  IButton* createButton() override { return new CButtonRectangle; }
  IScroll* createScroll() override { return new CScrollRectangle; }
};
 
//------------------------------------------------------------------
// 동그라미 팩토리 클래스
class CUIFactory_Circle : public IUIFactory
{
public:
  IButton* createButton() override { return new CButtonCircle; }
  IScroll* createScroll() override { return new CScrollCircle; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
  CUIFactory_Rectangle mRectangleFactory;
   
  IButton* pRectangleButton = mRectangleFactory.createButton();
  IScroll* pRectangleScroll = mRectangleFactory.createScroll();
   
  pRectangleButton->print();
  pRectangleScroll->print();
 
  delete pRectangleButton;
  delete pRectangleScroll;
 
  return 0;
}

템플릿을 이용하여 구현하면 아래와 같다.


//------------------------------------------------------------------
// 버튼 인터페이스
class IButton
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 스크롤 인터페이스
class IScroll
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 사각 버튼 클래스
class CButtonRectangle : public IButton
{
public:
  void print() override { cout << "CButton Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 사각 스크롤 클래스
class CScrollRectangle : public IScroll
{
public:
  void print() override { cout << "CScroll Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 버튼 클래스
class CButtonCircle : public IButton
{
public:
  void print() override { cout << "CButton Circle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 스크롤 클래스
class CScrollCircle : public IScroll
{
public:
  void print() override { cout << "CScroll Circle" << endl; }
};
 
//------------------------------------------------------------------
// 추상 팩토리 템플릿 인터페이스 (템플릿 메소드 패턴 적용)
template<typename T>
class AbstractFactory
{
public:
  T* Create() { return createProduct(); }
 
protected:
  virtual T* createProduct() = 0;
};
 
//------------------------------------------------------------------
// 팩토리 템플릿 클래스 (세부 객체 생성 전담)
template<typename T1, typename T2>
class ConcreteFactory : public AbstractFactory<T1>
{
private:
  T1* createProduct() override { return new T2; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
  ConcreteFactory<IButton, CButtonCircle> mCircleFactory;
  ConcreteFactory<IScroll, CScrollRectangle> mRectangleFactory;
 
  IButton* pCircleButton = mCircleFactory.Create();
  IScroll* pRectangleScroll = mRectangleFactory.Create();
 
  pCircleButton->print();
  pRectangleScroll->print();
 
  delete pCircleButton;
  delete pRectangleScroll;
 
  return 0;
}

참조 : http://devsw.tistory.com
         http://copynull.tistory.com



Factory Method Pattern (팩토리 매서드 패턴)

Factory Method Pattern

개체 생성시 직접적으로 생성자를 호출하지 않고, Factory Method를 이용하여 생성한다.

유용한 경우

1. 구체적으로 어떤 클래스의 객체를 생성해야할지 미리 알지 못할 경우 유용하다. 구체적으로 생성될 객체는 하위 클래스에 의해 결정이 되며 하위 클래스는 계속 확장이 가능하다.
2. 클래스들에게 개별 객체의 생성 책임을 분산시켜 객체의 종류별로 객체 생성과 관련된 부분을 국지화 시킬 때 유용하다.

장점
1. 어떤 객체를 생성할 것인지와는 무관하게 동일한 형태로 프로그래밍이 가능하다. 이 것은 두개의 상위 클래스가 있기 때문에 가능하다.
2. 직접 생성자를 호출해서 객체를 생성하는 것보다 훨씬 유연하고 확장성 있는 구조이다.
3. 추후에 객체 생성방법이 바뀌더라도 Factory Method 만 수정하면 된다.

단점

1. 생성할 객체의 종류가 달라질때 마다 새로운 하위 클래스를 정의해야 한다. 이는 불필요하게 많은 클래스를 정의해야 한다는 문제점이 있다.

가장 간단한 예제는 다음과 같다.

class Product { ... };

class UserA {
public:
  void doSomething {
    Product p = new Product();
  }
};

class UserB {
public:
  void doSomethong {
    Product p = new Product();
  }
};

 위의 Code는 Product를 생성자를 호출함으로 직접 생성하고 있다. 위의 경우 만약 Product의 생성자가 매개변수를 가져야 하는 식으로 바뀔 경우 UserA, UserB 및 기타 생성자를 호출한 모든 Code를 다 수정해야 한다. 하지만 Factory Method를 이용하여 생성한 경우 해당 Method만 수정하면 되므로 유지보수성이 좋아진다.

class Product { ... };

class Factory {
public:
  static Product* getProduct {
    return new Product(); // 생성자에 변화가 생길 경우 여기만 수정하면 됨
  }
};

class UserA {
public:
  void doSomething {
    std::tr1::shared_ptr<Product> p(Factory::getProduct());
  }
};

class UserB {
public:
  void doSomethong {
    std::tr1::shared_ptr<Product> p(Factory::getProduct());
  }
};

 Factory Method를 사용하는 형식으로 고친 Code이다. 스마트 포인터 중 shared_ptr을 사용해서 혹시나 실수로 포인터를 지우지 않는 실수를 미연에 방지했다. 이 경우 생성자 쪽에 변화가 생길경우 Factory Method만을 수정하면 된다.

 조금 더 일반적인 예제를 들어보겠다.



 unit에는 marine 과 tank의 2가지 종류가 있고, 사용자 입장에서는 fire()라는 함수만을 이용하면 된다. 그리고 unit을 생성하기 위한 Factory로는 building 이라는 기본 클래스가 있고 그 아래 marine 과 tank의 생성을 담당하는 파생 클래스가 각각 존재한다.

#include "stdafx.h"
#include <iostream>
 
class unit{
public:
    enum{ marine = 0, sniper = 1, tank = 2, bike = 3 };
    virtual void fire() = 0;
};
class marine : public unit{
public:
    void fire() { std::cout << "marine Fire!\n"; }
};

class tank : public unit{
public:
    void fire() { std::cout << "tank Fire!\n"; }
};
 
class building{
public:
    unit* newUnit(int v){
        unit* pUnit = CreateUnit(v);
        return pUnit;
    }
protected:
    virtual unit* CreateUnit(int v) = 0;
};
 
class barrack : public building{
protected:
    unit* CreateUnit(int v) {
        if(v == unit::marine) return new marine;
        else  return NULL;
    }
};
 
class factory : public building{
protected:
    unit* CreateUnit(int v) {
        if(v == unit::tank)  return new tank;
        else  return NULL;
    }
};
 
int _tmain(int argc, _TCHAR* argv[]) {
    int input = unit::tank;
    unit* pUnit;   // 어떤 unit을 만들지 몰라 unit 포인터를 만들었습니다.
    if(input == unit::marine){
        barrack b;    // 배럭에서 유닛을 생성하기 위해 배럭을 하나 만들어 주었습니다.
        pUnit = b.newUnit(input);       // 입력값에 의해 마린 유닛을 만들었습니다.
    }
    else if (input == unit::tank){      // 전차를 만듭니다.
        factory f;                      // 공장을 만들어주고.
        pUnit = f.newUnit(input);       // 유닛을 만들었습니다.
    }
    else
        return 0;
     
    if(pUnit) pUnit->fire(); // 유닛이 무엇이던간에 일단 공격합니다.
 
    return 0;
}

참조 : http://devsw.tistory.com/61
         http://www.youtube.com/watch?v=ApwZxNOFOaI



Design Pattern Relationship




출처 : http://copynull.tistory.com

GoF Design Pattern Reference Card




첨부파일 : GoF_Design_Pattern_Reference_Card.pdf