Factory Method 패턴
- 서브 클래스가 인스턴스를 결정하도록 하고 책임을 위임하는 패턴
- 객체의 생성을 서브 클래스에 위임하는 패턴
- 조건에 맞게 객체를 다르게 생성
- 결합도 줄이고 유지보수 용이
- 템플릿 메소드 패턴 사용
- (Virtual - Constructor)
객체 생성 방법)
- 생성자 (new 연산자)를 사용하여 직접 생성
- 객체 생성 클래스 / 메소드 (factory class / method) 사용 -> 객체 생성을 추상화
문제점1)
다양한 종류의 피자 (객체)를 생성 변경 추가 제거 가능
생성자를 사용하여 객체 생성
Pizza orderPizza(String type)
{
Pizza pizza;
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“greek”) {
pizza = new GreekPizza();
} else if (type.equals(“pepperoni”) {
pizza = new PepperoniPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
피자 타입 변경(추가, 제거) 時 영향을 받음.
(∵) Depends on concretion: new ConcreteClass().
적용할 설계 원칙
- OCP : 변경 가능한 부분을 분리
- 분리한 부분을 추상화
- create() method in a Factory class
- 분리한 부분을 구성과 위임을 사용하여 통합 (Composition of Factory)
public class PizzaFactory
{
// 모든 클라이언트가 새로운 객체를 인스턴스화 하기위해 사용할 것 이다.
public Pizza createPizza(String type)
{
Pizza pizza = null;
if(type.equals("cheese)){
pizza = new CheesePizza();
}else if(type.equals("pepperoni)){
pizza = new PepperoniPizza();
} else if(type.equals("clam)){
pizza = new ClamPizza();
} else if(type.equals("veggie)){
pizza = new VeggiePizza();
}
return pizza;
}
}
확장시 createPizza 메소드만 변경
public class PizzaaStore
{
PizzaFactory factory;
public PizzaStore(PizzaFacttory factory){
this.factory = factory;
}
public Pizza orderPizza(String type)
{
Pizza pizza;
pizza = factory.createPizzaa(type); // 확장시 영향을 받지 않는다.
pizza.prepare();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
// other methods here
}
문제점2)
여러 피자가게들이 서로 다른 피자를 만들 경우
해결)
서로 다른 유형의 객체를 생성하는 경우
생성자 대신 factory method 를 사용하여 객체를 생성
- Creator 는 공통의 factory method 인터페이스를 정의
- 실제 생성은 하위의 concrete creator에게 맡김
- 각 concrete creator는 각자의 방법(factoryMethod)으로 생성
Product
public abstract class Pizza
{
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
void prepare() {
System.out.println(“Preparing “ + name);
System.out.println(“Tossing dough...”);
System.out.println(“Adding sauce...”);
System.out.println(“Adding toppings: “);
for (int i = 0; i < toppings.size(); i++) {
System.out.println(“ “ + toppings.get(i));
}
}
void bake() {
System.out.println(“Bake for 25 minutes at 350”);
}
void cut() {
System.out.println(“Cutting the pizza into diagonal slices”);
}
void box() {
System.out.println(“Place pizza in official PizzaStore box”);
}
public String getName() {
return name;
}
}
public class ChicagoCheesePizza extends Pizza{
public ChicagoCheesePizza() { name = "Chicago 스타일 소스와 치즈 피자"; }
}
public class ChicagoVegePizza extends Pizza{
public ChicagoVegePizza() { name = "Chicago 스타일 소스와 야채 피자."; }
}
public class NYCheesePizza extends Pizza{
public NYCheesePizza() { name = "NY 스타일 소스와 치즈 피자"; }
}
public class NYVegePizza extends Pizza{
public NYVegePizza() { name = "NY 스타일 소스와 야채 피자."; }
}
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = “NY Style Sauce and Cheese Pizza”;
dough = “Thin Crust Dough”;
sauce = “Marinara Sauce”;
toppings.add(“Grated Reggiano Cheese”);
}
}
Creator
public abstract class PizzaStore
{
// 피자 생성 인터페이스만 정의; 실제 생성은 subclass에게 맡김.
protected abstract Pizza createPizza(String type);
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
// other methods here
}
Factory Method : createPizza
// 예시 구상 클래스
public class DependentPizzaStore extends PizzaStore
{
// Factory Method: 자신의 피자를 생성
public Pizza createPizza(String style, String type) {
Pizza pizza = null;
if (style.equals(“NY”)) {
if (type.equals(“cheese”)) {
pizza = new NYStyleCheesePizza();
} else if (type.equals(“veggie”)) {
pizza = new NYStyleVeggiePizza();
} else if (type.equals(“clam”)) {
pizza = new NYStyleClamPizza();
} else if (type.equals(“pepperoni”)) {
pizza = new NYStylePepperoniPizza();
}
} else if (style.equals(“Chicago”)) {
if (type.equals(“cheese”)) {
pizza = new ChicagoStyleCheesePizza();
} else if (type.equals(“veggie”)) {
pizza = new ChicagoStyleVeggiePizza();
} else if (type.equals(“clam”)) {
pizza = new ChicagoStyleClamPizza();
} else if (type.equals(“pepperoni”)) {
pizza = new ChicagoStylePepperoniPizza();
}
} else {
System.out.println(“Error: invalid type of pizza”);
return null;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
public class NYStore extends PizzaStore
{
@Override
protected Pizza createPizza(String pizzaType) {
if(pizzaType.equals("치즈피자")) return new NYCheesePizza();
else if(pizzaType.equals("야채피자"))return new NYVegePizza();
else if(pizzaType.equals("시카고 야채 피자"))return new ChicagoVegePizza();
return null;
}
}
public class ChicagoPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String pizzaType) {
if(pizzaType.equals("치즈피자")) return new NYCheesePizza();
else if(pizzaType.equals("야채피자"))return new NYVegePizza();
else if(pizzaType.equals("시카고 야채 피자"))return new ChicagoVegePizza();
return null;
}
}
메인
public class PizzaTestDrive {
public static void main(String[] args) {
Pizza pizza;
PizzaStore store;
store = new NYStore();
pizza = store.orderPizza("치즈피자");
System.out.println("ordered a " + pizza.getName() + "\n");
pizza = store.orderPizza("시카고 야채 피자");
System.out.println("ordered a " + pizza.getName() + "\n");
store = new ChicagoPizzaStore();
pizza = store.orderPizza("치즈피자");
System.out.println("ordered a " + pizza.getName() + "\n");
pizza = store.orderPizza("야채피자");
System.out.println("ordered a " + pizza.getName() + "\n");
}
}
The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate.
Factory Method lets a class defer(맡기다) instantiation to subclasses.
All factory patterns encapsulate object creation. The Factory Method Pattern encapsulates object creation by letting subclasses decide what objects to create.
The abstract Creator gives you an interface with a method for creating objects, also known as the “factory method”
Any other methods implemented in the abstract Creator are written to operate on products produced by the factory method.
Only subclasses actually implement the factory method and create products.
Factory Method VS Abstract Factory
Factory Method : 하나의 메소드가 여러 종류의 객체를 생성
Abstract Factory : 같은 종류의 여러 개의 객체를 생성할 수 있는 클래스를 생성
head first design patterns
댓글