본문 바로가기

Knowledge/Design Pattern

팩토리 메소드 패턴 (Factory Method Pattern)

TestClass test = new TestClassA();


여기서 new는 무엇일까 ? new를 사용한다는 것은 구상 클래스의 인스턴스를 만들겠다는 뜻이다.


그렇다면 만약 다음과 같은 상황을 가정해보자.


TestClass test;


if(A){

test = new TestClassA();

}else if(B){

test = new TestClassB();

}else if(C){

test = new TestClassC();

}else if .....


일련의 구상클래스들이 있을 때는 어쩔 수 없이 위와 같은 코드를 만들어야 하는 경우가 있다.

이렇게 코드를 짜게되면 나중에 변경하거나 확장할 때 어려움을 겪는다.


문제가 "new"에 있는걸까?

new 자체에 문제가 있는 것은 아니다. 문제가 있는건 바로 "변화" 때문.

인터페이스에 맞춰서 코딩을 하면 여러 변화를 이겨낼 수 있다.

--> 변화에 대해 닫혀있는 코드 (OCP)가 된다.

어떻게 코드를 변경하는 것이 좋을까?

나중에 코드가 바뀔 수 있는 부분을 찾아내서 바뀌지 않는 부분과 분리시켜야한다.

위 코드처럼 인스턴스를 생성하는 코드가 나중에 확장되거나 삭제될 수 있는 부분이다.

객체 생성코드만 따로 빼서 객체를 만드는 일만 전담하는 다른 객체를 집어넣는다.

그렇게해서 만들어진 객체 생성을 처리하는 클래스를 팩토리라고 부른다.


public class SimpleFactory{

public TestClass createClass(String type){

TestClass test = null;


if(type.equals("A")){

test = new TestClassA();

} else if(type.equals("B")){

test = new TestClassB();

} else if(type.equals("C")){

test = new TestClassC();

} else if(type.equals("D")){

test = new TestClassD();

}


return test;

}

}

  }

하지만 이러한 간단한 팩토리는 디자인패턴이라고 할 수 없다.

코드를 좀 더 유연성있게 만드는 프레임워크가 필요하다.


클래스를 확장해서 서브클래스에서 어떤 클래스를 만들지를 결정하게 함으로써 객체 생성을 캡슐화하는 것이다.

이것을 팩토리 메소드 패턴이라고 한다.


팩토리 메소드 패턴 (Factory Method Pattern)


팩토리 메소드 패턴에서는 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 객체를 만들지는

서브클래스에서 결정하게 된다.


예를 들어 PizzaStore라는 추상 클래스에 orderPizza() 메소드와 createPizza() 추상 메소드가 있다.

orderPizza() 메소드에서 추상메소드 createPizza()를 호출해서 객체를 생성하는 방식이다.

여기에 팩토리 메소드 패턴을 적용하려면 추상클래스 PizzaStore를 확장해서 서브클래스를 만든다.



여기서 SeoulPizzaStore와 BusanPizzaStore는 PizzaStore클래스를 확장해서 createPizza()를 구현한다.

이렇게 확장한 서브클래스에서는 createPizza("인자") 에 따라서 객체를 생성한다.

이렇게 구현하게 되면 orderPizza() 입장에서 볼 때는 서브클래스에서 어떤 객체를 만들지를 결정한다고 볼 수 있다.




여기서 디자인 원칙중 하나를 적용해서 코드를 수정한 것이라고 볼 수 있다.

그 디자인 원칙은 바로 "의존성 뒤집기 원칙" 이다.


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


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

순서를 맨 위에서부터 생각하는 대신 어떤 것을 추상화 시킬 수 있을지를 생각해보자.