[cs - Java ] Factory method 패턴

링딩·2023년 5월 2일
0

Computer Science

목록 보기
47/49

이 글을 통해 작성하였습니다.

  • GoF의 디자인 패턴(개정판) / 에릭 감마, 리처드 헬름, 랄프 존슨, 존 블라시디스 공저 / 김정아 역

팩토리 메소드 패턴?

  • 디자인 패턴 중 목적의 '생성패턴'에 속한다.

◽ 의미

  • 객체를 생성하기 위해 인터페이스를 만듭니다. 어떤 클래스의 인스턴스를 만들지를 서브클래스에서 결정하도록 합니다.
  • 팩토리 메소드를 이용하면 인스턴스를 만드는 일을 서브클래스로 미룰 수 있습니다.
  • 생성할 객체의 클래스를 국한하지 않고 객체를 생성


어떤 상황에서 주로 쓸까?

  • 어떤 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을 때
  • 생성할 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때
  • 객체 생성의 책임을 몇 개의 보조 서브클래스 가운데 하나에게 위임하고, 어떤 서브클래스가 위임자인지에 대한 정보를 국소화시키고 싶을 때

예제

다음은 피자를 주문하는 예제입니다.

1) 먼저 Creator 클래스인 PizzaStore를 만든다.
2) 이 클래스는 createPizza라는 팩토리 메소드를 실행해서 pizza를 생성한다.

public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.box();

        return pizza;
    }

    abstract Pizza createPizza(String type);
}

  1. PizzaStore 클래스를 확장해 각 지점을 만들고 지점마다 피자를 만드는 것을 책임지도록 createPizza 팩토리 메소드를 오버라이딩한다.
//NYPizzaStore.class
public class NYPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String item) {
        if ("cheese".equals(item)) {
            return new NYStyleCheesePizza();
        } else if ("veggie".equals(item)) {
            return new NYStyleVeggiePizza();
        } else if ("clam".equals(item)) {
            return new NYStyleClamPizza();
        } else {
            return null;
        }
    }
}


//ChicagoPizzaStore.class
public class ChicagoPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String item) {
        if ("cheese".equals(item)) {
            return new ChicagoStyleCheesePizza();
        } else if ("veggie".equals(item)) {
            return new ChicagoStyleVeggiePizza();
        } else if ("clam".equals(item)) {
            return new ChicagoStyleClamPizza();
        } else {
            return null;
        }
    }
}



  1. Product 클래스인 Pizza 를 만들고 이 클래스를 확장해 구상 클래스를 만들어보자.
public abstract class Pizza {
    String name;
    String dough;
    String sauce;

    void prepare() {
        System.out.println("preparing~~ " + name);
    }

    void bake() {
        System.out.println("baking~~");
    }

    void box() {
        System.out.println("boxing~~");
    }
    
    public String getName() {
        return name;
    }
}

  1. Product 클래스Pizza를 확장하여 3가지의 시카고 스타일 피자를 만들었다.

//1. 치즈피자
public class ChicagoStyleCheesePizza extends Pizza {
    public ChicagoStyleCheesePizza() {
        name = "ChicagoStyleCheesePizza";
    }
}

//2. clam 피자
public class ChicagoStyleClamPizza extends Pizza {
    public ChicagoStyleClamPizza() {
        name = "ChicagoStyleClamPizza";
    }
}


//3. Veggie피자
public class ChicagoStyleVeggiePizza extends Pizza {
    public ChicagoStyleVeggiePizza() {
        name = "ChicagoStyleVeggiePizza";
    }
}


  1. main 메소드에서 예제를 실행해보자.
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();

Pizza nyCheesePizza = nyStore.orderPizza("cheese");
Pizza nyClamPizza = nyStore.orderPizza("clam");

Pizza chicagoCheesePizza = chicagoStore.orderPizza("cheese");
Pizza chicagoClamPizza = chicagoStore.orderPizza("clam");
  • 결과
preparing~~ NYStyleCheesePizza
baking~~
boxing~~
preparing~~ NYStyleClamPizza
baking~~
boxing~~
preparing~~ ChicagoStyleCheesePizza
baking~~
boxing~~
preparing~~ ChicagoStyleClamPizza
baking~~
boxing~~

지점과 주어진 타입(cheeze, clam)에 따라서 다른 피자를 만드는 것을 확인할 수 있다.



장점과 단점

장점

  • 팩토리 메서드 패턴은 응용프로그램에 국한된 클래스가 코드에 종속되지 않도록 해준다
  • 응용프로그램은 Product 클래스에 정의된 인터페이스와만 동작하도록 코드가 만들어지기 때문에, 사용자가 정의한 어떤 ConcreteProduct 클래스가 와도 동작할 수 있다.
  • SRP
    -> 객체는 단 하나의 책임만 가져야 한다는 원칙
  • OCP
    -> 개방 폐쇄 원칙
    => "기능을 변경하거나 확장할 수 있으면서 그 기능을 사용하는 코드는 수정하지 않는다."

단점

  • 패턴 구현에 의한 코드가 복잡해질 수 있다.
profile
초짜 백엔드 개린이

0개의 댓글