팩토리 메서드 패턴 정의
객체 생성과 관련된 디자인 패턴으로 객체 생성 역할을 담당하면서 각 클라이언트에서 구현 클래스에
직접 의존하지 않도록 분리하는 패턴이다. 물론 새로운 클래스가 추가 되었을때 Facotory클래스를
수정해야하긴 한다.
한마디로, 인스턴스를 생성을 서브 클래스로 책임을 넘겨준다.
장점
- 확장에 열려있고 변경에 닫혀있게 된다.
- 중복된 코드가 줄어들고 상속하는 모든 클래스가 동일한 공통 로직을 사용할 수 있다.
- 객체가 변화할 여지가 있을때 상속하는 클래스를 하나 더 만들어서 구현해주면 된다.
단점
- 많은 클래스 파일이 생긴다.
패턴 적용전
이미지 표현
코드
간략하게 PizzaStore코드만 보여주겠다
PizzaStore.java
public class PizzaStore {
Pizza orderPizza(String pizza_type) {
Pizza pizza = new Pizza(); //
//피자 종류를 바탕으로 올바른 구상 클래스의 인스턴스를 만들고,
//pizza 인스턴스 변수에 그 인스턴스를 대입함
//모든 피자 클래스는 Pizza 인터페이스를 구현함
if(pizza_type.equals("cheese")) {
pizza = new CheesePizza();
} else if(pizza_type.equals("greek")) {
pizza = new GreekPizza();
} else if(pizza_type.equals("pepperoni")) {
pizza = new PepperoniPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
문제점
위 방식에서 피자 종류가 추가 된다고 생각을 해보자. 그러면 PizzaStore에서 else if문이 하나
더 늘고 추가로 00Pizza 클래스가 추가 될 것 이다. 그렇다면 PizzaStore에는 피자 종류 선택과
피자 조리 코드가 동시에 있는 와중에 계속해서 코드가 변경되야한다.
해결방법
피자 종류를 선택할 수 있게 관리하는 PizzaFactory를 둔다. 기존 PizzaStore에 존재하던
피자 고르는 if절 부분을 PizzaFactory옮겨준다. 이렇게 되면 새로운 피자가 추가되더라도
PizzaStore은 코드를 수정할 필요가 없고 관련 내용이 들어간 PizzaFactory코드만 수정해주면 된다.
패턴 적용 후
적용 이미지
코드
PizzaStore.java
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}
public Pizza orderPizza(String pizza_type) {
Pizza pizza;
pizza = factory.createPizza(pizza_type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
SimplePizzaFactory.java
//원래 피자선택이랑 조리를 Store에서 다했다면 이제는 분리해서 Store에서는 조리만
//PizzaFactory에서는 피자선택후 피자종류반환만 전담
public class SimplePizzaFactory {
public Pizza createPizza(String pizza_type) {
Pizza pizza = null;
if(pizza_type.equals("cheese")) {
pizza = new CheesePizza();
}else if(pizza_type.equals("pepperoni")) {
pizza = new PepperoniPizza();
}
return pizza;
}
}
Pizza.java
public abstract class Pizza {
String pizza_name;
public void prepare() {
System.out.println("도우, 소스, 토핑을 하는중..");
}
public void bake() {
System.out.println("화덕에 피자를 굽습니다..");
}
public void cut() {
System.out.println("피자를 자릅니다..");
}
public void box() {
System.out.println("상자에 피자를 담습니다..");
}
public String getName() {
return pizza_name;
}
}
CheesePizza.java
public class CheesePizza extends Pizza{
public CheesePizza() {
pizza_name = "치즈피자";
}
}
PizzaTest.java
public class PizzaTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
SimplePizzaFactory factory = new SimplePizzaFactory();
PizzaStore store = new PizzaStore(factory);
System.out.println("\n주문받기");
Pizza pizza1 = store.orderPizza("cheese");
System.out.println(pizza1.getName());
System.out.println("\n주문받기");
Pizza pizza2 = store.orderPizza("pepperoni");
System.out.println(pizza2.getName());
}
}
결과값
피자 종류는 여러개지만 구현하는 방법은 비슷해서 CheesePizza코드만 추가했다.
추가로 Pizza를 인터페이스가 아닌 추상클래스로 구현했는데 인터페이스로 구현해도 된다.
'디자인 패턴' 카테고리의 다른 글
[디자인패턴] 추상 팩토리 패턴 (0) | 2023.12.03 |
---|---|
[디자인 패턴] 템플릿 메서드 패턴 (1) | 2023.12.01 |
[디자인패턴] 데커레이터 패턴 (0) | 2023.12.01 |
[디자인패턴] 옵저버 패턴 (0) | 2023.10.31 |
[디자인패턴] 커맨드 패턴 (0) | 2023.10.29 |