블로그 이미지
Kanais
Researcher & Developer 퍼즐을 완성하려면 퍼즐 조각들을 하나 둘씩 맞춰나가야 한다. 인생의 퍼즐 조각들을 하나 둘씩 맞춰나가다 보면 인생이란 퍼즐도 완성되는 날이 오려나...?

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

05-05 16:47

Recent Post

Recent Comment

Recent Trackback

Archive

2015. 4. 16. 10:08 Programming/Design Pattern



참고 서적 : GOF의 디자인패턴 – Addison Wesley – 에릭감마, 리처드 헬름, 랄프 존슨, 존 블리시디스 지음. 김정아 옮김.


Abstract Factory란?

구체적인 클래스를 지정하지 않고 관련성을 갖는 객체들의 집합을 생성하거나 서로 독립적인 객체들의 집합을 생성할 수 있는 인터페이스를 제공하는 패턴입니다.

 

Abstract Factory의 구조



l  AbstractFactory : 개념적 제품에 대한 객체를 생성하는 연산으로 인터페이스를 정의합니다.

l  ConcreateFactory : 구체적인 제품에 대한 객체를 생성하는 연산을 구현합니다.

l  AbstractProduct : 개념적 제품 객체에 대한 인터페이스를 정의합니다.

l  ConcreateProduct : 구체적으로 팩토리가 생성할 객체를 정의하고, Abstract Factory가 정의하는 인터페이스를 구현합니다.

l  Client : AbstractFactory와 AbstractProduct클래스에 선언된 인터페이스를 사용 합니다.

ConcreateFactory가 자동차를 생산하는 공장이라고 한다면,

AbstractProduct는 자동차의 종류(소형차, 중형차 등)이고, Product는 자동차(티코,아반테 등)일 겁니다. 그리고 AbstractFactory는 자동차 회사라고 보시면 됩니다.

 


 

AbstractFactory의 활용성

-      객체가 생성되거나 구성 . 표현되는 방식과 무관하게 시스템을 독립적으로 만들고자 할 때

-      여러 제품군 중 하나를 선택해서 시스템을 설정해야 하고 한번 구성한 제품을 다른 것으로 대체할 수 있을 때

  (여기서 제품군이란 특정한 상황과 목적에 맞게 생성된 객체들의 집합을 말합니다. )

-      관련된 제품 객체들이 함께 사용되도록 설계되었고, 이 부분에 대한 제약이 외부에도 지켜지도록 하고 싶을 때

-      제품에 대한 클래스 라이브러리를 제공하고, 그들의 구현이 아닌 인터페이스를 노출시키고 싶을 때

 

Abstract Factory와 Factory Method 공통점

추상 클래스를 사용하여 제품을 생산해 낸다는 점이 공통점입니다.

 

Abstract Factory와 Factory Method 차이점

Abstract Factory? 
제품군을 만들기 위한 추상형식을 제공한다.
제품이 생성되는 방법은 서브클래스에서 정의된다
.
클라이언트에서 서로 연관된 일련의 제품을 만들어야 할때, 즉 제품군을 만들어야 할 때 사용한다. 


Factory Method?
클래스를 확장하고, 팩토리 메소드를 오버라이드한다.
팩토리메서드의 사용->서브클래스를 통해서 객체를 생성한다.

클라이언트와 구상 형식을 분리시켜주는 역할.
클라이언트 코드와 인스턴스를 만들어야 할 구상 클래스를 분리시켜야 할 때 활용한다. 어떤 구상 클래스를 필요로 하게 될지 미리 알 수 없는 경우에도 매우 유용하다.

 


 

Abstract Factory를 쓰는 이점과 부담

l  이점

1.    구체적인 클래스를 분리

추상 팩토리 패턴을 쓰면 응용프로그램이 생성할 객체의 클래스를 제어할 수 있습니다. 팩토리는 제품 객체를 생성하는 과정과 책임을 캡슐화한 것이기 때문에, 구체적인 구현 클래스가 사용자에게서 분리됩니다. 일반 프로그램은 추상 인터페이스를 통해서만 인스턴스를 조작합니다. 제품 클래스 이름이 구체 팩토리의 구현에서 분리되므로, 사용자 코드에는 나타나지 않는 것입니다.

 

2. 제품군을 쉽게 대체할 수 있다.

구체 팩토리의 클래스는 응용프로그램에서 한 번만 나타나기 때문에 응용프로그램이 사용할 구체 팩토리를 변경하기는 쉽습니다. 또한, 구체 팩토리를 변경함으로써 응용프로그램은 서로 다른 제품을 사용할 수 있게 변경됩니다. 추상 팩토리는 필요한 모든 것을 생성하기 때문에 전체 제품군은 한번에 변경이 가능합니다.

 

3. 제품 사이의 일관성을 증진

   - 하나의 군 안에 속한 제품 객체들이 함께 동작하도록 설계되어 있을 때, 응용프로그램은 한 번에 오직 한 군에서 만든 객체를 사용하도록 함으로써 프로그램의 일관성을 갖도록 해야 합니다. 추상 팩토리를 쓰면 이 점을 아주 쉽게 보장할 수 있습니다.

 

l  부담

새로운 종류의 제품을 제공하기 어려움

   - 새로운 종류의 제품을 만들기 위해 기존 추상 팩토리를 확장하기가 쉽지 않습니다. 생성되는 제품은 추상 팩토리가 생성할 수 있는 제품 집합에만 고정되어 있기 때문입니다. 만약 새로운 종류의 제품이 등장하면 팩토리의 구현을 변경해야 합니다. 이는 추상 팩토리와 모든 서브클래스의 변경을 가져옵니다. 즉, 인터페이스가 변경되는 새로운 제품을 생성하는 연산이 추가되거나, 기존 연산의 반환 객체 타입이 변경되었으므로, 이를 상속받는 서브클래스 모두 변경되어야 합니다.


 

Abstract Factory구현 기법

 

1.    팩토리를 단일체(Singleton)로 정의

   - 전형적으로 응용프로그램은 한 제품군에 대해서 하나의 ConcreateFactory인스턴스만 있으면 됩니다. 즉, 갖가지 제품의 종류를 만들어 내는 팩토리는 제품군에 대해서 하나면 되는 것입니다. 그러므로 단일체로 구현하는 것이 바람직합니다.

 

2. 제품을 생성

   - AbstractFactory는 단지 제품을 생성하기 위한 인터페이스를 선언하는 것이고, 그것을 생성하는 책임은 Product의 서브클래스인 ConcreateProduct에 있습니다. 이를 위한 가장 공통적인 방법은 각 제품을 위해서 팩토리 메서드를 정의하는 것입니다. AbstractFactory는 각 제품 생성을 위한 팩토리 메서드를 재정의함으로써 각 제품의 인스턴스를 만듭니다. 이 구현은 간단하지만, 제품군이 약간 다르다면 각 제품군을 위한 새로운 구체 팩토리 서브클래스가 필요합니다.

 

3. 확장 가능한 팩토리들을 정의

   - AbstractFactory에는 생성할 각 제품의 종류별로 서로 다른 연산을 정의합니다. 이 제품들의 종류는 연산 시그니처를 보면 알 수 있습니다. CreateProductA를 통해 ProductA를 만듭니다. 새로운 종류의 제품이 추가되면 AbstractFactory의 인터페이스에도 새로운 연산을 추가해야 합니다. 좀더 유연하게 하려면 생성할 객체를 매개변수로 만들어 연산에 넘기면 됩니다. 그리고 매개변수에다가 생성할 객체의 종류를 표현합니다.


 

예제 프로그램

 



  디자인

클래스 명

역할

CarFactory

AbstractFactory에 해당하는 클래스.

MUFactory

DogCar와 SoccerCar를 생성함.

TSFactory

CatCar와 BaseballCar를 생성함.

MiniCar

DogCar와 CatCar의 공통된 함수를 선언.

DogCar

MiniCar의 함수를 재정의 함.

CatCar

MiniCar의 함수를 재정의 함.

SportsCar

SoccerCar와 BaseballCar의 공통된 함수를 선언.

SoccerCar

SportsCar의 함수를 재정의 함.

BaseballCar

SportsCar의 함수를 재정의 함.

 

 

 


 

  CarFactory 클래스와 CarFactory클래스에서 파생된 MUFactory클래스와 TSFactory클래스

 



 

l CarFactory 멤버필드

멤버필드 명

설 명

Minicars

Minicar를 보관하는 벡터

sportscars

sportscar를 보관하는 벡터

 

l CarFactory 멤버 메서드

메서드 명

설 명

.ctor(void)

기본 생성자

CreateMiniCar

MiniCar타입의 개체를 생성 하는 가상함수.

CreateSportsCar

SportsCar타입의 개체를 생성 하는 가상함수.

DisposeMiniCar

매개변수로 받은 MiniCar개체를 벡터에서 삭제한다.

DisposeSportsCar

매개변수로 받은 SportsCar개체를 벡터에서 삭제한다.

PushMiniCar

MiniCar개체를 벡터에 삽입한다.

PushSportsCar

SportsCar개체를 벡터에 삽입한다.

DisposeMiniCar

MiniCar개체가 벡터에 있다면 KillMiniCar실행

DisposeSportsCar

SportsCar개체가 벡터에 있다면 KillSportsCar 실행

KillMiniCar

MiniCar개체를 삭제한다.

KillSportsCar

SportsCar개체를 삭제한다.

 

CarFactory::CarFactory(void)

{

}

 

CarFactory::~CarFactory(void)

{

        DisposeMiniCars();

        DisposeSportsCars();

}

 

void CarFactory::PushMiniCar(MiniCar *minicar)

{

        minicars.push_back(minicar);

}

void CarFactory::PushSportsCar(SportsCar *sportscar)

{

        sportscars.push_back(sportscar);

}

bool CarFactory::DisposeMiniCar(MiniCar *minicar)

{

        miter seek = find(minicars.begin(),minicars.end(),minicar);

        if(seek != minicars.end())

        {

               minicars.erase(seek);

               delete minicar;

               return true;

        }

        return false;

}

bool CarFactory::DisposeSportsCar(SportsCar *sportscar)

{

        siter seek = find(sportscars.begin(),sportscars.end(),sportscar);

        if(seek != sportscars.end())

        {

               sportscars.erase(seek);

               delete sportscar;

               return true;

        }

        return false

}

 

void CarFactory::DisposeMiniCars()

{

        find_if(minicars.begin(),minicars.end(),KillMiniCar);

 

}

void CarFactory::DisposeSportsCars()

{

        find_if(sportscars.begin(),sportscars.end(),KillSportsCar);

}

 

bool CarFactory::KillMiniCar(MiniCar *minicar)

{

        delete minicar;

        return false;

}

bool CarFactory::KillSportsCar(SportsCar *sportscar)

{

        delete sportscar;

        return false;

}

 

CarFactory클래스의 CreateMiniCar메서드와 CreateSportsCar메서드를 MUFactory와 TSFactory에서 재정의해서 사용하고 있다. 하지만 MUFactory클래스에서 만들어진 MiniCar타입의 개체와 TSFactory클래스에서 만들어진 MiniCar타입의 개체는 다른 개체이다.

Client가 어느 Factory에 주문을 하느냐에 따라서 생산되는 Car는 다를 것이다. MUFactory에 주문을 한다면 DogCar가 생산되고, TSFactory에 주문을 한다면 CatCar가 생산될 것이다.

 

 

  MiniCar클래스와 MiniCar클래스에서 파생된

CatCar클래스 와 DogCar클래스

 



 

메서드 명

설 명

Smaile

클래스에 따라 다른 문자열이 출력된다.

 


 

  SportsCar클래스와 SportsCar로부터 파생된 SoccerCar클래스와 BaseballCar클래스

 



 

메서드 명

설 명

Playball

클래스에 따라 다른 문자열이 출력된다.



'Programming > Design Pattern' 카테고리의 다른 글

[Design Pattern] Template Method  (0) 2015.04.16
[Design Pattern] Bridge Pattern  (0) 2015.04.16
[Design Pattern] Builder  (0) 2015.04.16
posted by Kanais