Flutter

[Flutter] 팩토리 패턴(Factory pattern)

hymndaniel 2023. 2. 28. 13:14

유튜버 개발하는 남자 님의 강의 내용과 다른 블로그의 내용을 정리한 내용입니다.

팩토리 패턴은 언제, 왜 사용하는가?

팩토리 패턴의 예시

소프트웨어에서 패턴이란 어떠한 문제를 이미 검증된 솔루션이 있어, 규칙대로 만들면 문제를 해결할 수 있는 것이다. 마치 제품을 설계하고 공장에서 찍어 내듯이, 사용자가 어떤 모델을 만드는데 관여하지 않고 필요한 형태(설계)로 요청을 해서 모델을 만들고자 할 때, 그 역할을 하는 것이 팩토리 패턴이다.

 

장점
팩토리 패턴은 싱글톤 패턴이다. 싱글톤 패턴은 생성자를 여러번 호출해도 초기에 만들어진 하나의 생성자만 사용하는 것이다. 때문에 팩토리를 사용하면 static을 사용한 효과를 얻게된다. factory는 싱글톤 패턴을 사용할 때 쓰는 예약어이다. 객체를 생성하지 않고도 패턴을 사용할 수 있고, 설계 도면이 바뀌어도 클라이언트에서는 모델 생성에 관여하지 않기 때문에 의존성을 낮출 수 있다.

 

팩토리 패턴을 사용하지 않았을 때 
void main() {
  var selectedPizza = PizzaType.Cheese;
  Pizza pizza;
  
  switch(selectedPizza) {
    case PizzaType.Pineapple:
      pizza = PineapplePizza();
      break;
    case PizzaType.Mushroom:
      pizza = MushroomPizza();
      break;
     case PizzaType.Cheese:
      pizza = CheesePizza();
      break;
  }
  
  print(pizza.getPrice());
}

enum PizzaType(Pineapple, Mushroom, Cheese);

abstract class Pizza {
   double getPrize();
} 

class PineapplePizza implemants Pizza{
  double prize = 20.0;
  @override
  double getPrize() {
    return prize;
  }
}

class Mushroom implemants Pizza{
  double prize = 10.0;
  @override
  double getPrize() {
    return prize;
  }
}

class Cheese implemants Pizza{
  double prize = 15.0;
  @override
  double getPrize() {
    return prize;
  }
}

 

팩토리 패턴을 사용했을 때
void main() {
 Map<String, dynamic> json = {
   "type":PizzaType.Pineapple,
 };
 print(Pizza.pizzaFactory(PizzaType.Pineapple).getPrice());
}

...

abstract class Pizza {
  double getPrize();
  factory Pizza.fromJson(Map<String, dynamic> json) {
    switch(json["type"] as PizzaType) {
      case PizzaType.Pineapple:
        return PineapplePizza();
      case PizzaType.Mushroom:
        return MushroomPizza();
      case PizzaType.Cheese:
        return CheesePizza();
    }
  }
} 

...

 

 

위 예시의 코드는 피자 가게에서 피자를 주문할때 피자 종류에 따라 가격을 출력해주는 예제이다. 팩토리 패턴을 사용하지 않고 먼저 구현해본다.
enum PizzaType { HamMushroom, Deluxe, Seafood }
파자의 종류를 선택할 수 있는 타입을 열거 타입으로 생성하였다.
abstract class Pizza {
  double getPrice();
}
추상 클래스로 getPrice라는 기능을 하는 Pizza 클래스를 만든다. 이렇게 하면 Pizza를 상속받는 구현체(피자 객체)들은 모두 가격(double)을 반환하는 getPrice를 구현해줘야 한다.
class HamAndMushroomPizza implements Pizza {
  double price = 8.5;

  @override
  double getPrice() {
    return price;
  }
}

class DeluxePizza implements Pizza {
  double price = 10.5;
  @override
  double getPrice() {
    return price;
  }
}

class SeafoodPizza implements Pizza {
  double price = 11.5;
  @override
  double getPrice() {
    return price;
  }
}
그리고 피자의 종류대로 객체를 만들어준다.

 

그 다음 팩토리 패턴으로 변경해본다. 가장 먼저 추상 클래스 Pizza를 수정한다.
abstract class Pizza {
  double getPrice();
  static pizzaFactory(PizzaType type) {
    switch (type) {
      case PizzaType.HamMushroom:
        return HamAndMushroomPizza();
      case PizzaType.Deluxe:
        return DeluxePizza();
      case PizzaType.Seafood:
        return SeafoodPizza();
    }
  }
}
여기서 보시면 아까 메인 함수에서 swich문으로 사용자가 원하는 피자가 무엇인지에 따라 분기를 해줬던 부분이 추상 클래스로 들어와 있으면서 static으로 선언이 되어있습니다. static으로 선언을 하게 되면 클래스 변수로 선언이 된 것입니다. 인스턴스 변수가 아닌 클래스 변수 즉 생성자 없이도 접근이 가능한 상태입니다. 이것이 팩토리 패턴에 장점 중 하나입니다. 생성자 없이도 어디서든 원하는 피자 객체를 생성할 수 있는 것. 그리고 두 번째 장점은 클라이언트( 피자 객체를 만들어 사용해야하는 부분 이 예제에서는 main 이 되겠습니다. ) main 에서는 더 이상 어떤 피자 객체가 있고 그 피자 객체에는 어떤 값들이 들어가야 하는지 전혀 몰라도 알아서 피자객체를 만들어 넘겨주게 됩니다.  _개발하는 남자 블로그
void main() {
  print(Pizza.pizzaFactory(PizzaType.HamMushroom).getPrice());
}

 

팩토리 패턴이 유용한 경우는 피자 객체를 만들때 추가적인 정보를 받아야할 때처럼 처음 설계와 달라지는 경우이다.  팩토리 패턴이 사용되지 않은 경우, 피자 객체를 참조하는 모든 소스를 수정해야하는 상황이 발생한다. 

그리고 보통은 객체를 생성하려고할 때 Map 타입의 여러 데이터가 들어오게 되면서 우리가 자주 사용하는 fromJson의 형태로 사용한다. 자세한 내용은 개남님 블로그 참조

 

 

 

 

 

 

 

https://www.youtube.com/watch?v=ZikfiBnFMk8 

 

https://www.youtube.com/watch?v=ICaYCojSPko&t=447s 

https://github.com/sudar-life/factory_pattern_example

 

GitHub - sudar-life/factory_pattern_example: 팩토리패턴을 사용하는 이유에대해서 간단한 예제로 알아보기

팩토리패턴을 사용하는 이유에대해서 간단한 예제로 알아보기. Contribute to sudar-life/factory_pattern_example development by creating an account on GitHub.

github.com

 

https://sudarlife.tistory.com/entry/%ED%94%8C%EB%9F%AC%ED%84%B0%EB%8B%A4%ED%8A%B8-%ED%8C%A9%ED%86%A0%EB%A6%ACFactory-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A1%9C-%EC%A0%95%EB%B3%B5%ED%95%98%EA%B8%B0

 

[ 플러터/다트 ] 팩토리(Factory) 패턴 예제로 정복하기~!

안녕하세요 개발하는남자 개남입니다. 오랜만에 포스팅을 하게 되었는데 최근에 질문받은 것 중에 플러터를 하다보면 많이 접하게 되지만 무심코 넘어갔던 부분인 factory를 사용하는 이유 왜 쓰

sudarlife.tistory.com

 

728x90