팩토리 패턴은 객체 생성을 위한 인터페이스를 정의하지만 서브클래스가 인스턴스화할 클래스를 결정하도록 하는 생성 패턴입니다. 팩토리 패턴을 사용하면 클래스가 인스턴스화를 하위 클래스로 연기할 수 있습니다.
"제품" 상속 계층 구조가 있고 여기에 다른 제품을 추가할 수 있는 경우 팩토리 패턴을 사용하세요. (Product는 Factory 메소드에 의해 반환되는 객체를 의미합니다)
심플팩토리에 대해 모르시는 분들은 미리 공부해두시는 걸 추천드려요. 자료는 많지만 제 블로그는 여기입니다.
이전에는 Simple Factory를 도입하여 클라이언트 코드에서 객체 생성을 분리하면서 다양한 버거를 생산할 수 있었습니다. 우리 버거 가게는 성공적으로 수익을 올렸고 이제 다른 지역에 다른 버거 가게를 오픈하고 싶습니다.
orderBurger 메소드는 고객에게 버거를 판매하는 프로세스를 정의합니다.
// This is our Client public class BurgerShop { public Burger orderBurger(BurgerType type) { // Factory is responsible for object creation Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; } }
이정도면 괜찮은데, 다른 버거집을 런칭하면 어떨까요? "SeaSideBurgerShop"을 시작한다고 가정하면 SeaSideBurgerShop 클래스를 만들고 자체 orderBurger()를 정의하겠습니다. 문제는 토핑 추가를 잊어버리거나 잘못된 순서로 작업을 진행하는 경우가 있다는 점입니다.
문제가 있는 SeaSideBurgerShop:
public class SeaSideBurgerShop { public Burger orderBurger(BurgerType type) { Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.wrap(); // Wrap a burger before grilling a patty?? burger.grillPatty(); // They forget to add toppings!! return burger; } }
이를 방지하려면 프로세스를 수행하는 순서와 수행할 작업을 정의하면서도 유연성을 유지할 수 있는 버거 매장용 프레임워크가 필요합니다.
버거샵
이 추상 클래스에는 orderBurger() 및 createBurger()라는 두 가지 메서드가 있습니다. orderBurger()는 수행할 작업과 프로세스가 수행되어야 하는 순서를 정의합니다. 이는 버거 가게가 일부 프로세스를 잊어버리거나 프로세스 순서를 엉망으로 만드는 것을 방지합니다. creatBurger()는 서브클래스가 어떤 종류의 버거를 만들지 결정할 수 있게 해주는 추상 메서드입니다.
BurgerShop 하위 클래스
이러한 콘크리트 BurgerShops는 콘크리트 버거를 만드는 일을 담당합니다. BurgerShop을 확장하는 각 하위 클래스는 createBurger()에 대한 자체 구현을 정의합니다.
버거
이 추상 클래스는 모든 버거 사이에 공통 인터페이스를 제공하고 기본 동작을 정의합니다.
버거 하위 클래스
콘크리트 제품은 다음과 같습니다. Burger 클래스를 확장하는 한 메서드를 재정의하여 특정 동작을 구현할 수 있습니다.
// This is our Client public class BurgerShop { public Burger orderBurger(BurgerType type) { // Factory is responsible for object creation Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; } }
public class SeaSideBurgerShop { public Burger orderBurger(BurgerType type) { Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.wrap(); // Wrap a burger before grilling a patty?? burger.grillPatty(); // They forget to add toppings!! return burger; } }
public enum BurgerType { BEEF, CHICKEN, FISH, VEGGIE }
public abstract class Burger { public BurgerType type; public List<String> toppings = new ArrayList<>(); public void prepareBun() { System.out.println("Preparing a bun"); } public void grillPatty() { if (type == null) { throw new IllegalStateException("pattyType is undefined"); } System.out.println("Grill a " + type + " patty"); } public void addToppings() { for (String item : toppings) { System.out.println("Add " + item); } } public void wrap() { System.out.println("Wrap a burger up"); } }
public class CityStyleBeefBurger extends Burger { public CityStyleBeefBurger() { type = BurgerType.BEEF; List<String> items = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce"); toppings.addAll(items); } }
public class CityStyleVeggieBurger extends Burger { public CityStyleVeggieBurger() { type = BurgerType.VEGGIE; List<String> items = List.of("smoked paprika", "garlic chips", "crushed walnuts", "veggie sauce"); toppings.addAll(items); } }
public class SeaSideStyleBeefBurger extends Burger { public SeaSideStyleBeefBurger() { type = BurgerType.BEEF; // Localized toppings for beef burger in seaside area List<String> items = List.of("lettuce", "pickle slices", "tomato slice", "salty sauce"); toppings.addAll(items); } // Uses localized wrapping paper @Override public void wrap() { System.out.println("Wrap with a paper with nice sea scenery"); } }
public class SeaSideStyleFishBurger extends Burger { public SeaSideStyleFishBurger() { type = BurgerType.FISH; // Localized toppings for fish burger in seaside area List<String> items = List.of("red onion slices", "salty sauce", "fried shrimps"); toppings.addAll(items); } // Uses localized wrapping paper @Override public void wrap() { System.out.println("Wrap with a paper with nice sea scenery"); } }
public abstract class BurgerShop { // This method provides a framework for each burger shops to order burgers public Burger orderBurger(BurgerType type) { Burger burger = createBurger(type); burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; } // This is our factory method. Subclasses will override this method, // provide their own implementation, determine which kind of burger gets made. public abstract Burger createBurger(BurgerType type); }
출력:
public class CityBurgerShop extends BurgerShop { @Override public Burger createBurger(BurgerType type) { return switch (type) { case BEEF -> new CityStyleBeefBurger(); case VEGGIE -> new CityStyleVeggieBurger(); default -> throw new IllegalArgumentException("unknown city burger type"); }; } }
여기에서 모든 디자인 패턴 구현을 확인할 수 있습니다.
GitHub 저장소
추신
기술 블로그를 처음 작성하는 초보입니다. 글쓰기를 개선하기 위한 조언이 있거나 혼란스러운 점이 있으면 댓글을 남겨주세요!
읽어주셔서 감사합니다 :)
위 내용은 팩토리 패턴의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!