티스토리 뷰

Computer/Analysis n Design

[Design Pattern]Abstract Factory

인생이글케쉬우냐 2009. 5. 14. 14:32

출처 카페 > Effective progr.. | yoonga87
원본 http://cafe.naver.com/ec8study/1

- Abstract Factory -

한글로 해석하면 추상공장이란 뜻이다.

디자인 패턴이란게 별로 어려운게 없는게 말 그대로 이해하면 그 패턴의 역할을 직관적으로 알 수 있다.

Abstract Factory는 생성패턴중 하나인데, 공장처럼 생산품을 찍어내는 객체이다. (클래스)

그럼 왜 Factory가 아닌 Abstract Factory 인가?

Factory의 기본적인 인터페이서를 정의해 주는 Factory의 형식과 틀을 제공해 주는 클래스가 필요하기 때문이다.

다시 말하면 우리가 Abstract Factory로 만들 클래스는 Factory들의 추상클래스가 되는 것이다.

추상 클래스란 상속받을때 인터페이스만 상속받을수 있는 클래스를 말한다. 예를 들면,

// 추상클래스이기 때문에 인스턴스화 하려고 하면 컴파일러가 에러를 발생시킨다.

 class AbstractFactory {

 public:

  virtual ProductA* CreateProductA() = 0; // 정의 안함

  virtual ProductB* CreateProductB() = 0; // 마찬가지

};

// 추상클래스의 인터페이스만 상속받는 구체적클래스..

class ConcreteFactory : public AbstractFactory {

public:

   virtual ProductA* CreateProductA(); // 정의가 필요

   virtual ProductB* CreateProductB(); // 마찬가지

};

전체적인 그림으로 AbstractFactory를 살펴보자.

 

 

이 공장들은 키보드와 마우스를 뽑아내는 공장이라고 해보자.. 그럼 AbstractFactory의 인터페이스는 대강 이럴것이다.

class AbstractFactory {

public:

 virtual  Mouse* CreateMouse ( ) = 0;

 virtual KeyBoard* CreateKeyBoard ( ) = 0;

};

 

그럼 이제 이걸 상속받는 ConcreteFactory는 인터페이스를 정의해야 한다. 여기서 StandardFactory은 평범한 마우스와 키보드를 만든다고 하자.

class StandardFactory : public AbstractFactory {

public:

 virtual Mouse* CreateMouse() // 추상클래스의 인터페이스를 정의해야 하니깐.. 똑같이 써줘야한다.

 { return new StandardMouse; } //

 virtual KeyBoard* CreateKeyBoard()

 { return new StandardKeyBoard; } //

};

여기서 의문을 제기하는 사람이 있을 것이다. CreateMouse나 CreateKeyBoard의 리턴형은 모두 Mouse*와 KeyBoard* 인데

왜 StandardMouse, StandardKeyBoard를 리턴시켜줄까? 라고 말이다.

위의 그림과 비교해 보면, AbstractProductA를 ProductA1과 ProductA2가 상속받는것이 보일 것이다...

여기선 Mouse는 AbstractProductA에 해당하는 추상클래스이고, KeyBoard는 AbstractProductB에 해당한다.

당연히 StandardMouse는 ProductA1에 해당하고, StandardKeyBoard는 ProductB1에 해당한다.

쉽게 말해서 StandardMouse와 StandardKeyBoard는 Mouse와 KeyBoard를 상속받은 것이다.

(Mouse와 KeyBoard는 추상클래스.. 하지만 꼭 추상클래스로 해줄 필요는 없다.. 융통성있게 코딩해야 한다. )

그럼 저 코드는 아무런 이상(에러)없이 작동할 것이라고 추측할 수 있다.

이렇게 코드를 짜놓으면 디자인패턴 장점중 하나인 확장성이 생긴다는 것을 알 수 있다..

만약 우리는 무선마우스와 무선키보드를 만드는 공장을 하나 만들고 싶다고 해보자.

그럼 이 3가지만 해주면 된다.

1. Mouse를 상속받는 RemoteMouse 클래스를 하나 만든다.

2. KeyBoard를 상속받는 RemoteKeyBoard 클래스도 하나 만든다.

3. 마지막으로 AbstractFactory 를 상속받는 RemoteFactory 를 하나 만들어 준다.

그럼 끝이다.

남은 일이라고는 RemoteFactory가 추상클래스로부터 상속받은 인터페이스를 채우는 일만 남았다.

class RemoteFactory : public AbstractFactory {

public:

 virtual Mouse* CreateMouse()

 { return new RemoteMouse; }

 virtual KeyBoard* CreateKeyBoard()

 { return new RemoteKeyBoard; }

};

디자인 패턴에서 중요한 것중 하나는 클래스를 상속받을때, 인터페이스 위주로 상속받고 인터페이스에 맞추어 구현을 짜라는 것이다.

나도 디자인패턴을 공부해 보기 전까지는 구현에 맞추어 class 메소드를 정의하곤 했는데 이러면 클래스 하나가 생성될때마다,

서로 다른 인터페이스를 선언하고 정의해 주어야 하기 때문에 class간에 공통점도 없고 사용하기도 불편했다.

앞으로 디자인패턴에서 나오는 많은 기법들은 인터페이스 위주의 상속을 많이 사용하기 때문에 디자인패턴을 공부하기 위해선 이런 개념도 잘 알아두고, 나중에는 자기것으로 만들어야 하겠다.


반응형

'Computer > Analysis n Design' 카테고리의 다른 글

[Plug-In] AmaterasUML- 첫번째  (0) 2009.05.14
UML - 시퀀스 다이어그램 기본  (0) 2009.05.14