"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > 심플팩토리

심플팩토리

2024년 11월 17일에 게시됨
검색:544

심플팩토리란?

단순한 팩토리는 디자인 패턴이 아닙니다. 이는 단순히 클라이언트 코드에서 객체 생성을 분리합니다. 즉, Simple Factory는 인스턴스화 로직을 별도의 클래스로 이동하여 객체 인스턴스화를 캡슐화합니다.

간단한 팩토리는 종종 팩토리 패턴과 혼동됩니다. 차이점을 명확히 하기 위해 Simple Factory에 대해 알아보겠습니다. 또한 Simple Factory를 학습하면 Factory 패턴을 쉽게 이해할 수 있습니다.

Simple Factory는 어떤 문제를 해결할 수 있나요?

구체적인 구현을 위한 프로그래밍은 애플리케이션 유지 관리를 매우 어렵게 만들기 때문에 피해야 합니다. 인터페이스에 프로그래밍하는 것이 항상 바람직합니다. 클라이언트 코드에서 구체적인 클래스를 인스턴스화하는 경우 Simple 팩토리가 클라이언트에서 객체 생성을 분리할 수 있으므로 Simple 팩토리가 유용합니다. 이는 우리의 애플리케이션을 더욱 확장 가능하고 유지 관리하기 쉽게 만듭니다.

문제

버거샵 시스템을 개발하고 있습니다. 쇠고기 버거, 치킨 버거 등 다양한 버거를 만드는 시스템이 필요합니다.

첫 번째 시도는 다음과 같습니다.

// Client orders a burger
Burger orderBurger(String type) {
    Burger burger;

    if (type.equals("beef")) {
        burger = new BeefBurger();
    } else if (type.equals("chicken")) {
        burger = new ChickenBurger();
    } else if (type.equals("fish")) {
        burger = new FishBurger();
    }

    burger.prepareBun();
    burger.grillPatty();
    burger.addToppings();
    burger.wrap();

    return burger;
}

문제는 인터페이스가 아닌 구현을 위해 코딩하고 있다는 것입니다. 어디? if 문을 사용하고 버거 유형을 기반으로 구체적인 클래스를 인스턴스화합니다.
왜 문제가 됩니까? 우리의 클라이언트 코드는 객체 생성과 밀접하게 결합되어 유연성이 떨어집니다!! 더 이상 생선 버거를 판매하지 않고 채식 버거를 판매하기 시작한다고 가정해 보겠습니다. 클라이언트 코드를 방문하여 수정해야 합니다. 즉, 수정을 위해 닫혀있지 않습니다.

해결책

문제를 해결하기 위해 객체 생성만 담당하는 별도의 클래스를 만들 수 있습니다. 그러면 클라이언트 코드는 객체 생성에 대해 걱정할 필요가 없으며 추상화에 의존할 수 있습니다. 이 기술은 "다양한 내용 캡슐화"로 알려져 있습니다. 구체적인 객체 인스턴스화에 대한 코드는 자주 변경될 것으로 예상하지만 prepareBun(), grillPatty(), addToppings(), Wrap() 프로세스는 미래의 모든 버거에서 동일하게 유지될 가능성이 높습니다.
Simple Factory의 장점은 다른 클래스에서 재사용이 가능하다는 것입니다. SimpleBurgerFactory.createBurger() 메소드를 사용하는 BurgerRestaurant, BurgerCateringShop과 같은 다른 클라이언트 클래스가 있을 수도 있습니다.

Simple Factory

  1. 고객
    클라이언트는 SimpleBurgerFactory를 통해 특정 버거 객체를 인스턴스화합니다. 클라이언트 관점에서 보면 어떤 콘크리트 버거가 생성될지 알 수 없습니다. 즉, 객체 생성 로직이 이제 클라이언트에서 분리되었습니다.

  2. 심플버거팩토리
    이 클래스는 변화하는 것, 즉 객체 생성 로직을 캡슐화합니다! createBurger()는 클라이언트가 이 클래스를 사용하여 객체를 인스턴스화하기를 원하기 때문에 정적 메서드로 선언됩니다(물론 인스턴스화하기 전에는 인스턴스를 가질 수 없습니다!). createBurger()는 생성해야 하는 버거 유형을 결정하기 위해 BurgerType 열거형을 허용합니다.

  3. 버거
    이 추상 클래스는 모든 버거 사이에 공통 인터페이스를 제공하고 기본 동작을 정의합니다.

  4. 버거 하위 클래스
    콘크리트 제품은 다음과 같습니다. Burger 클래스를 확장하는 한 메서드를 재정의하여 특정 동작을 구현할 수 있습니다.

구조

Simple Factory

암호

public enum BurgerType {
    BEEF,
    CHICKEN,
    FISH,
    VEGGIE
}
// Abstract Product
public abstract class Burger {

    public BurgerType burgerType;
    public List toppings = new ArrayList();

    public void prepareBun() {
        System.out.println("Preparing a bun");
    }

    public void grillPatty() {
        if (burgerType == null) {
            throw new IllegalStateException("pattyType is undefined");
        }
        System.out.println("Grill a "   burgerType   " patty");
    }

    public void addToppings() {
        for (String item : toppings) {
            System.out.println("Add "   item);
        }
    }

    public void wrap() {
        System.out.println("Wrap a burger up");
    }
}
// Concrete product
public class BeefBurger extends Burger {

    public BeefBurger() {
        burgerType = BurgerType.BEEF;
        List items = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce");
        toppings.addAll(items);
    }
}
// Concrete product
public class VeggieBurger extends Burger {

    public VeggieBurger() {
        burgerType = BurgerType.VEGGIE;
        List items = List.of("smoked paprika", "garlic chips", "crushed walnuts", "veggie sauce");
        toppings.addAll(items);
    }

    // Concrete product can implement specific behavior that differs from other products
    @Override
    public void wrap() {
        System.out.println("Wrapping paper shouldn't print any meats but vegetables");
    }
}
// Simple factory, responsible for instantiating an object
public class SimpleBurgerFactory {

    public static Burger createBurger(BurgerType type) {
        return switch (type) {
            case BEEF -> new BeefBurger();
            case CHICKEN -> new ChickenBurger();
            case FISH -> new FishBurger();
            case VEGGIE -> new VeggieBurger();
            default -> throw new IllegalArgumentException("unknown burger type");
        };
    }
}
public class Client {

    public static void main(String[] args) {
        Burger burger = orderBurger(BurgerType.VEGGIE);
        System.out.println(burger); // Check if the object is actually veggie burger
    }

    public static 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;
    }
}

산출:

Preparing a bun
Grill a VEGGIE patty
Add smoked paprika
Add garlic chips
Add crushed walnuts
Add veggie sauce
Wrapping paper shouldn't print any meats but vegetables
com.factories.simpleFactory.VeggieBurger@9807454

함정

  • 객체 인스턴스화를 위한 의사결정 코드는 때때로 더 복잡해질 수 있습니다. 그러한 경우 대신 Factory 메서드를 사용하는 것이 좋습니다.

팩토리 패턴과의 비교

  • 간단한 팩토리에는 일반적으로 생성할 제품 유형을 결정하는 하나의 팩토리 클래스가 있는 반면, 팩토리 패턴은 여러 개의 팩토리를 도입할 수 있습니다.
  • 간단한 팩토리는 종종 정적 메서드를 사용하여 객체를 생성하므로 호출하기는 쉽지만 확장하기는 어렵습니다. 반면, 팩토리 메소드는 모든 팩토리에 대한 인터페이스 역할을 하는 슈퍼 클래스의 추상 메소드를 사용하며 서브클래스는 객체 인스턴스화를 위한 구체적인 구현을 제공합니다.

여기에서 모든 디자인 패턴 구현을 확인할 수 있습니다.
GitHub 저장소


추신.
기술 블로그를 처음 작성하는 초보입니다. 글쓰기를 개선하기 위한 조언이 있거나 혼란스러운 점이 있으면 댓글을 남겨주세요!
읽어주셔서 감사합니다 :)

릴리스 선언문 이 글은 https://dev.to/sota_333ad4b72095606ab40c/simple-factory-3bnl?1에서 복제됩니다.1 침해 내용이 있는 경우, [email protected]으로 연락하여 삭제하시기 바랍니다.
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3