- 예제 코드 Diagram -



* Factory Method Pattern :

객체를 생성하기 위한 인터페이스를 만든다. 

어떤 클래스의 인스턴스를 만드는 것을 서브클래스에서 결정하도록 한다. 

이 패턴을 이용하면 인스턴스를 만드는 일을 서브클래스에게 맡길 수 있다.



아래 그림을 참고해서 위의 그림을 설명하자면,

(출처 : http://www.cnblogs.com/zhuqiang/archive/2012/05/05/2484930.html )

Pizza 라는 추상 클래스(or 인터페이스)는 Product, 이를 상속받은 피자들이 Concrete Product.

PizzaStore 라는 추상 클래스(or 인터페이스)Creator, 이를 상속받은 체인점들이 ConcreteCreator 에 해당된다.

그리고 createPizza() 라는 메소드는 factoryMethod() 에 해당된다.


PizzaStore 는 생산자로서 Pizza 를 생산할 뿐이지 실질적으로 어떤 피자가 만들어질 지는 전혀 모른다.

(여기서 PizzaStore 는 클라이언트 코드다)

실질적으로 어떤 피자가 만들어질 지는 Pizza 의 서브클래스에 따라 결정이 된다.



* 의존성 뒤집기 원칙 (Dependency Inversion Principle) :

- 추상화된 것에 의존하도록 만들어라. 구상 클래스에 의존하지 않도록 만들어야한다.

- 이를 지키는 데 도움이 될만한 3가지 가이드 라인

. 어떤 변수에도 구상 클래스에 대한 레퍼런스를 저장하지 않는다.

. 구상 클래스에서 유도된 클래스를 만들지 않는다.

. Base 클래스에 이미 구현되어 있는, 모든 서브클래스에서 공유하는 메소드를 오버라이드하지 않는다.

 


* Abstract Factory Pattern :

서로 연관된, 또는 의존적인 객체들로 이루어진 제품군(Product Family)을 생성하기 위한 인터페이스를 제공한다.

구상 클래스는 서브클래스에 의해 만들어진다.

예제의 NYPizzaStore 클래스의 createPizza() 코드 中

Pizza pizza = null;

PizzaIngredientFactory inredientFactory = new NYPizzaIngredientFactory();

pizza = new CheesePizza(ingredientFactory);


PizzaIngredientFactory 가 위 그림의 Abstract Factory, NYPizzaIngredientFactory 가 Concrete Factory,

NYPizzaStore 가 Client 에 해당한다.


그 외에 Abstract Product A 는 피자 도우 정도 되고

그 하위의 Product A1, A2 는 각각 얇은 도우, 두꺼운 도우 정도라고 생각하면 된다.

마찬가지로 Abstract Product B 도 치즈 정도에 해당, Product B1, B2 는 모짜렐라 치즈 등에 해당된다.


Concrete Factory 1 에서는 Product A1, B1 을 제품군으로 이루고 있고,

Concrete Factory 2 에서는 Product A2, B2 를 제품군으로 이루고 있다.


그리고 위 그림의 Factory 가 생산자(Creator)라고 생각하면 

Abstract Factory 패턴에서는 Factory Method 패턴이 쓰이는 걸 볼 수 있다.



* Factory Method Abstract Factory

- 공통점

서브클래스를 통해서 객체를 만듦으로서 클라이언트(PizzaStore) 에서는

자신이 사용할 추상 형식(Pizza)만 알면 되고, Concrete 형식은 서브클래스에서 처리해준다.

즉, 클라이언트와 Concrete 형식을 분리시켜주는 역할을 한다.

객체 생성을 캡슐화해서 애플리케이션이 결합을 느슨하게 만들고 

특정 구현에 대한 의존성을 낮힐 수 있다.

- Factory Method

상속을 통해 Product 의 객체를 만든다. ex ) PizzaStore 추상 클래스의 createPizza() 를 오버라이드

클라이언트 코드와 인스턴스를 만드는 구상 클래스를 분리시켜야 할 때 활용할 수 있다.

- Abstract Factory

객체 구성을 통해 Product 의 객체를 만든다. ex ) pizza = new CheesePizza(ingredientFactory)

팩토리를 이용하고 싶으면 일단 인스턴스를 생성하고 추상 형식을 써서 만든 코드(Pizza)에게 이를 전달.

Concrete Factory 구현할 때, 종종 Factory Method 패턴을 사용하는 경우가 있다.

일련의 연관된 제품을 하나로 묶을 수 있다는 장점이 있다.

단, 제품군에 제품을 추가시킬 경우 Abstract Factory 의 createProductC() 를 추가해야 하는데 요약하자면!

인터페이스를 바꿔야해서 모든 서브클래스에도 영향을 미치게 된다는 단점이 있다.



* 객체지향의 원칙 :

1) 바뀌는 부분은 캡슐화 한다.

2) 상속보다는 구성을 활용한다.

3) 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.

4) 서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.

5) 클래스는 확장에 대해서는 열려 있어야 하지만 코드 변경에 대해서는 닫혀 있어야 한다(OCP).

6) 추상화된 것에 의존해라. 구상 클래스에 의존해서는 안 된다(의존성 뒤집기 법칙).



이 장에서의 정리 :

- Factory 를 쓰면 객체 생성을 캡슐화 할 수 있다.

- Factory Method 패턴에서는 어떤 클래스에서 인스턴스를 만드는 일을 서브클래스에게 넘긴다.

- Abstract Factory 패턴에서는 구상 클래스에 직접 의존하지 않고도 

서로 관련된 객체들로 이루어진 제품군을 만들기 위한 용도로 쓰인다.

- Factory 는 구상 클래스가 아닌 추상 클래스 / 인터페이스에 맞춰서 코딩할 수 있게 해주는 강력한 기법이다!


by kelicia 2014. 5. 19. 02:13