////
Search

4장 - 팩토리 패턴

Created
2022/09/03 11:29
Tags
디자인패턴

요구사항

최첨단 피자 코드 만들기
피자 주문시 매개변수를 통해서 다양한 종류의 피자를 동적으로 생성하고 싶음!
다양한 스타일의 피자들이 생겨날 수 있음!

해결 방법 1 - 간단한 팩토리 만들기

피자의 생성 코드를 외부로 분리해서 객체 생성만을 처리하는 팩토리를 만들어냄
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("greek")) { pizza = new GreekPizza(); } else if (type.equals("PepperoniPizza")) { pizza = new PepperoniPizza(); } else { pizza = new DefaultPizza(); } return pizza; } }
Java
복사
객체 생성 캡슐화의 장점
피자 객체 생성을 캡슐화 해놓으면 여기저기 고칠 필요 없이 팩토리 클래스 하나만고치면 됨
서브클래스를 만들어서 메소드의 행동을 변경할 수 없음
간단한 팩토리는 디자인 패턴이라기 보다는 프로그래밍에서 자주쓰이는 관용구에 가까움
팩토리 메소드를 static으로 만들면?
팩토리 클래스의 인스턴스를 생성하지 않아도 됨
서브클래스를 만들어 생성 메소드 행동 변경이 불가

해결 방법 2 - 팩토리 메서드 패턴 적용

생산자 클래스 다이어그램
제품 클래스 다이어그램
피자집이 대성하여 다양한 지점이 생기게 되었고, 각 지점은 지역 특성에 맞는 피자인 시카고 피자를 만들어야 하는 요구사항이 추가됨
이 문제를 해결하기 위해서 PizzaStore과 피자 제작코드 전체를 하나로 묶어주는 프레임워크를 만들어야 함
물론 그렇게 만들면서도 유연성을 잃어버리면 안됨
createPizza() 메소드를 추상 메소드로 만들고 추상 클래스를 만들어 지역에 맞기 서브클래스를 만듦
public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } abstract Pizza createPizza(String type); }
Java
복사
모든 팩토리 패턴은 객체 생성을 캡슐화 함
팩토리 메소드 패턴은 서브클래스에서 어떤 클래스를 만들지 결정함으로써 객체 생성을 캡슐화 함
팩토리 메소드 패턴은 객체를 생성할 때 필요한 인터페이스를 만들어 냄
어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정

해결 방법 3 - 추상 팩토리 패턴

추상 팩토리 패턴은 구상 클래스에 의존하지 않고 설 연관되거나 의존적인 객체로 이루어진 제품군을 생산하는 인터페이스를 제공
구상 클래스는 서브 클래스에서 만들어 냄
public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClams(); } public class NYPizzaingredientFactory implements PizzaIngredientFactory{ @Override public Dough createDough() { return new ThinCrustdough(); } @Override public Sauce createSauce() { return new MarinaraSauce(); } @Override public Cheese createCheese() { return new ReggianoCheese(); } @Override public Veggies[] createVeggies() { Veggies veggies[] = { new Farlic(), new Onion(), new Mushroom(), new RedPepper() }; return veggies; } @Override public Pepperoni createPepperoni() { return new SlicedPepperoni(); } @Override public Clams createClams() { return new Freshclams(); } } public class CheesePizza extends Pizza{ PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } @Override public void prepare() { this.dough = ingredientFactory.createDough(); this.sauce = ingredientFactory.createSauce(); this.cheese = ingredientFactory.createCheese(); } }
Java
복사

DIP

추상화된 것에 의존하게 만들고 구상 클래스에 의존하지 않게 만든다.
의존성 뒤집기 원칙에서는 추상화를 더 많이 강조함
이 원칙에는 고수준 구성요소가 저수준 구성 요소에 의존하면 안 되며, 항상 추상화에 의존하게 만들어야 한다는 뜻
PizzaStore은 고수준 구성요소 피자 클래스는 저수준 구성 요소
의존성 뒤집기 원칙을 지키는 방법
변수에 구상 클래스의 레퍼런스를 저장하지 말자
구상 클래스에서 유도된 클래스를 만들지 말자
베이스 클래스에 이미 구현되어 있는 메소드를 오버라이드 하지 말자

정리

팩토리 메소드 패턴
구상 형식을 서브클래스에서 처리해주니까 자신이 사용할 추상 형식만 알면 된다.
추상 팩토리 패턴
제품근을 만드는 추상 형식을 제공, 서브클레스에서 정의