-
팩토리 패턴개발/flutter 2020. 9. 14. 17:54
팩토리 패턴
팩토리 패턴은 기본적으로 객체를 생성하는 패턴이다.
기본적으로 객체를 생성할떄 이렇게 생성한다.
Pizza orderPizza(String type){ Pizza pizza; if(type=='cheese'){ pizza = CheesePizza(); }else if(type=='pepperoni'){ pizza = PepperoniPizza(); } pizza.bake(); pizza.cut(); return pizza; }
위와같이 피자 타입에따라 피자를 생성할때 이런 식으로 생성한다.
하지만 예로 새로운 피자종류가 생기거나 치즈피자 판매를 중단하려면
코드를 수정해야한다.
저렇게 타입별로 피자를 생성하는 부분은 계속 바뀔수있으며 그럴 때마다 코드를 수정해야 하기 때문에
바뀌는부분은 캡슐화를 하는게 좋다.
그래서 팩토리 패턴을 사용한다.
abstract class Pizza{ prepare(); cut(); bake(); box(); } class CheesePizza implements Pizza{ @override bake() { print('bake CheesePizza'); } @override box() { print('box CheesePizza'); } @override cut() { print('cut CheesePizza'); } @override prepare() { print('prepare CheesePizza'); } } class PepperoniPizza implements Pizza{ @override bake() { print('bake PepperoniPizza'); } @override box() { print('box PepperoniPizza'); } @override cut() { print('cut PepperoniPizza'); } @override prepare() { print('prepare PepperoniPizza'); } }
우선 피자를 추상클래스로 정의하고 메소드를 정의해주고
피자 종류에따라 서브클래스를 만들어준다.
이제 피자 가게에서 피자를 만들때 팩토리를 사용해 타입을 넘겨준뒤 피자를 생성한다.
class PizzaStore{ PizzaStore({this.factory}); PizzaFactory factory; Pizza orderPizza(String type){ Pizza pizza; pizza = factory.createPizza(type); pizza.bake(); pizza.cut(); return pizza; } } class PizzaFactory{ createPizza(String type){ if(type=='cheese'){ return CheesePizza(); }else if(type=='pepperoni'){ return PepperoniPizza(); } } }
팩토리에서는 타입을받아 알맞은 피자를 리턴해주고
피자가게에서 orderPizza 에서 피자를 리턴받은뒤 굽고 잘라서 피자를 리턴해준다.
이번엔 조금 더 복잡한 피자구조를 만들어보자
치즈,페페로니 피자뿐만아니라 지역별로 나누려한다.
뉴욕 지점과 시카고 지점을 낼것이다. 그러므로 뉴욕치즈/뉴욕페페로니/시카고치즈/시카고페페로니 피자가있다.
피자부터 정의해주고
abstract class Pizza{ prepare(); cut(); bake(); box(); } class NYStyleCheesePizza implements Pizza{ @override bake() { print('bake NYStyleCheesePizza'); } @override box() { print('box NYStyleCheesePizza'); } @override cut() { print('cut NYStyleCheesePizza'); } @override prepare() { print('prepare NYStyleCheesePizza'); } } class NYStylePepperoniPizza implements Pizza{ @override bake() { print('bake NYStylePepperoniPizza'); } @override box() { print('box NYStylePepperoniPizza'); } @override cut() { print('cut NYStylePepperoniPizza'); } @override prepare() { print('prepare NYStylePepperoniPizza'); } } class ChicagoStyleCheesePizza implements Pizza{ @override bake() { print('bake ChicagoStyleCheesePizza'); } @override box() { print('box ChicagoStyleCheesePizza'); } @override cut() { print('cut ChicagoStyleCheesePizza'); } @override prepare() { print('prepare ChicagoStyleCheesePizza'); } } class ChicagoStylePepperoniPizza implements Pizza{ @override bake() { print('bake ChicagoStylePepperoniPizza'); } @override box() { print('box ChicagoStylePepperoniPizza'); } @override cut() { print('cut ChicagoStylePepperoniPizza'); } @override prepare() { print('prepare ChicagoStylePepperoniPizza'); } }
이번에는 피자가게 클래스를 추상클래스로 구현하고 뉴욕가게와 시카고 가게에서 상속 받을것이다.
abstract class PizzaStore{ Pizza pizza; orderPizza(String type){ pizza = createPizza(type); pizza.prepare(); pizza.cut(); pizza.bake(); pizza.box(); return pizza; } createPizza(String item); } class NYPizzaStore extends PizzaStore{ @override createPizza(String item) { if(item=='cheese'){ return NYStyleCheesePizza(); }else if(item=='pepperoni'){ return NYStylePepperoniPizza(); } } } class ChicagoPizzaStore extends PizzaStore{ @override createPizza(String item) { if(item=='cheese'){ return ChicagoStyleCheesePizza(); }else if(item=='pepperoni'){ return ChicagoStylePepperoniPizza(); } } }
이후 뉴욕에서 치즈피자를
시카고에서 페페로니 피자를 이런식으로 주문할수있다.
final ny = NYPizzaStore(); final chicago = ChicagoPizzaStore(); ny.orderPizza('cheese'); chicago.orderPizza('pepperoni');
객체를 생성하는 코드를 슈퍼클래스(추상클래스) 에서 분리하였음을 볼수있다.
슈퍼클래스에서는 어디서 어떤 피자를만드는지 모른다.
이와같이 팩토리 메소드 클래스(PizzaStore)에서는 객체를 생성하기 위한 인터페이스를 정의하고
어떤 클래스의 인스턴스를(뉴욕치즈피자) 만들지 서브 클래스(뉴욕피자 Store) 에서 정의한다.
즉 서브클래스에 인스턴스만드는것을 맡기는목적이다.
왜?
만약 팩토리 패턴을 사용하지 않고 같은 기능을 만든다면 다음과 같을것이다.
Pizza orderPizza(String location , String type){ Pizza pizza; if(location=='NY'){ if(type=='cheese'){ pizza = NYCheesePizza(); }else if(type=='pepperoni'){ pizza = NYPepperoniPizza(); } }else if(location=='Chicago'){ if(type=='cheese'){ pizza = ChicagoCheesePizza(); }else if(type=='pepperoni'){ pizza = ChicagoPepperoniPizza(); } } pizza.bake(); pizza.cut(); return pizza; }
그닥 나쁘지는 않다.
물론 location 의종류와 type 의 종류가 계속 증가할수록 코드는 복잡해질것이며
피자의 종류가 어떻게 바뀌냐에따라 orderPizza의 구현도 바뀔수도있다.
이를 orderPizza가 Pizza class(피자종류) 에 의존적이다 라고한다.
'개발 > flutter' 카테고리의 다른 글
카카오 로그인에러 AUTHORIZATION_FAILED: invalid android_key_hash or ios_bundle_id or web_site_url (0) 2020.09.24 Flutter-Your Xcode version may be too old for your iOS version 에러해결 (0) 2020.09.22 Flutter 카카오 로그인 구현하기 (0) 2020.09.09 [Flutter] 디바이스 별로 다른 Widget의 넓이 설정하기 (0) 2020.09.07 [Flutter] Dart 옵저버 패턴 Observer pattern (1) 2020.09.04