팩토리 메서드 패턴이란?
팩토리 메서드 패턴은 부모 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며, 자식 클래스가 어떤 객체를 생성할지 결정하도록 하는 패턴이기도 하다.
팩토리 메서드 패턴은 템플릿 메서드의 생성 패턴 버전으로 볼 수 있는데, 따라서 템플릿 메서드에 대해 알지 못한다면 해당 패턴을 먼저 이해하는 것이 좋다.
참고)
[디자인패턴] 템플릿 메서드 패턴(Template Method Pattern)이란? 템플릿 메서드 예시
팩토리 메서드 패턴은 객체를 생성할 때 어떤 클래스의 인스턴스를 만들지를 자식 클래스에게 위임한다.
클래스 다이어그램에서 각각은 다음을 의미한다.
- Creator : 최상위 공장 클래스로써 새로운 제품(Product) 객체들을 반환하는 팩토리 메서드를 선언한다.
- 객체 생성 처리 메서드( someOperation() ) : 객체 생성에 관한 전처리나 후처리를 템플릿화한 메서드이다.
- 팩토리 메서드( createProduct() ): 서브 공장 클래스에서 오버라이딩 할 객체 생성 추상 메서드이다.
- ConcreteCreator : 서브 공장 클래스로써 각각 걸맞는 제품 객체를 반환하도록 팩토리 메서드를 오버라이딩한다.
- Product : 제품 구현체를 추상화한 인터페이스
- ConcreteProductA : 팩토리 메서드로 생성한 제품 구현체
예시를 통해 쉽게 이해해보자.
팩토리 메서드 패턴 예시
당신이 피자 공장의 공장주라고 하자. 현재는 치즈피자 밖에 못 만드는 공장이라고 가정한다.
추후 공장의 확장을 위해 팩토리 메서드 패턴을 적용하기로 한다.
치즈 피자만 있을 때
특정 피자들(제품 구현체)과 그것들을 추상화한 인터페이스(Product)를 구현하자.
Product
public interface Pizza{
void putTopping(); // 객체생성 후처리 메서드
}
public class CheesePizza implements Pizza{
@Override
public void putTopping(){
System.out.println("치즈를 올립니다");
}
}
실제 제품 구현체인 CheesePizza와 그것을 추상화한 Pizza 인터페이스를 정의했다.
또한 객체 생성 후 실행될 후처리 메서드 putTopping() 메서드를 정의했다.
이제 피자를 생산할 팩토리를 구현하자.
이때 특정 피자들을 생산할 공장 클래스와 그것을 추상화한 최상위 공장 클래스를 구현하자.
Creator
abstract class PizzaFactory{
public Pizza newInstance(){
Pizza pizza = createPizza();
pizza.putTopping(); // 객체 생성 후처리 메서드
return pizza;
}
protected abstract Pizza createPizza();
}
public class CheesePizzaFactory extends PizzaFactory{
@Override
protected Pizza createPizza(){
return new CheesePizza();
}
}
추상 클래스로 최상위 공장 클래스인 PizzaFactory를 정의했다.
또한 newInstance() 메서드를 외부에서 호출해 구체 피자 클래스를 생성하도록 했다.
putTopping() 메서드는 객체 생성 처리 메서드로, 객체 생성 후처리 메서드이다.
서브 공장 클래스로 CheesePizzaFactory를 정의했다.
해당 클래스에서는 createPizza()를 오버라이딩해 실제로 생성되는 객체를 해당 클래스에서 정하도록 했다.
참고로 Java 8부터는 인터페이스에서 디폴트(default) 메서드를 사용할 수 있으므로 인터페이스로 최상위 공장 클래스를 만들어도 된다.
Client
PizzaFactory pizzaFactory = new CheesePizzaFactory();
Pizza pizza = pizzaFactory.newInstance();
실제로 사용하는 것은 위와 같이 하면 된다.
다이어그램으로 나타내자면 [그림 2]와 같다. 이해를 돕기 위해 간단히 그린 것이므로 정확하진 않다.
파인애플 피자를 추가
팩토리 메서드 패턴을 이용하면 확장에 용이하다는 것이다.
특정 클래스를 추가할 때 기존 코드의 변경이 없어도 된다.
예를 들어 피자 공장에 파인애플 피자를 추가한다고 하자.
기존 코드를 수정할 필요 없이 아래와 같은 코드만 추가하면 된다.
public class PineApplePizza implements Pizza{
@Override
public void putTopping(){
System.out.println("파인애플을 올립니다");
}
}
public class PineApplePizzaFactory extends PizzaFactory{
@Override
protected Pizza createPizza(){
return new PineApplePizza();
}
}
그리고 아래와 같이 사용하면 된다.
PizzaFactory pizzaFactory = new CheesePizzaFactory();
Pizza pizza = pizzaFactory.newInstance();
//기존 코드 변경 필요 없음
PizzaFactory pizzaFactory2 = new PineApplePizzaFactory();
Pizza pizza2 = pizzaFactory.newInstance();
다이어그램으로 나타내면 다음과 같다.
기존 클래스의 수정 없이 새로운 클래스를 간단하게 붙일 수 있었다.
팩토리 메서드 패턴의 장단점
장점
- 생성자와 구현 객체의 강한 결합을 제거할 수 있다.
- 객체 생성 후 전처리, 후처리를 지정할 수 있다.
- 단일 책임 원칙(SRP)을 준수할 수 있다.
- 수정에는 닫혀있고 확장에는 열린 개발/폐쇄 원칙(OCP)을 준수할 수 있다.
참고)
[프로그래밍 언어론] 객체 지향 설계 5원칙 (SOLID)란?
단점
- 코드가 복잡해질 수 있다.
- 구현체가 증가할 때마다 그에 맞는 공장 클래스를 만들어주어야 한다.
언제 사용하면 좋은가?
- 함께 동작해야 하는 객체들의 정확한 유형과 의존관계를 미리 모르는 경우
- 라이브러리 또는 프레임워크의 사용자들에게 내부 컴포넌트들을 확장하는 방법을 제공하고 싶을때
- 기존 객체들을 매번 재구축하는 대신 이들을 재사용하여 리소스를 절약하고 싶을 때
참고
2.https://refactoring.guru/ko/design-patterns/factory-method
'Computer Science > [디자인패턴]' 카테고리의 다른 글
[디자인패턴] 템플릿 메서드 패턴(Template Method Pattern)이란? 템플릿 메서드 예시 (0) | 2023.07.18 |
---|---|
[디자인패턴] 빌더 패턴(Builder Pattern)이란? 빌더 패턴 예제 (0) | 2023.07.17 |
[디자인패턴] 싱글톤 패턴(Singleton Pattern)이란? (0) | 2023.07.13 |