[디자인패턴] 팩토리 메소드 패턴 (Factory Method Pattern)

in #kr-dev6 years ago (edited)

디자인 패턴 이름은 많이 들었었는데, 얕게라도 본적이 없었다. 남는 시간에 조금씩 정리해 보고자 한다.

팩토리 패턴을 사용할 때

팩토리 패턴은 다음의 가정이 성립할 떄 유용하다.

  • 기본 가정
    • 로직에서 개체를 만들고 이를 사용한다.
    • 로직에서 사용되는 개체는 다양한 유형이 존재하고 군집화 가능하다.
    • 개체군은 공유하는 인터페이스로 추상화 가능하다.
    • 개체군에 속한 개체를 바꿔도 로직은 정상적으로 작동해야 한다.

즉, 개체를 만들고 사용하는 로직이 있는데, 이 로직이 유연하게 여러 유형의 개체를 다룰 수 있게 하는거다.

부가적인 효과로, 객체 생성 부분을 나중에 커스터마이즈 할 수 있게 된다.

개체 생성 함수 (a.k.a 팩토리 메소드?)

목표 달성을 위해 먼저 개체를 생성하고 반환하는 함수를 만든다. 다수의 객체를 생성하고 반환할 수 있으면 형식은 크게 상관 없다.

def get_drink(type_string=None):
    if(type_string is 'beer'):
        return Beer() # Beer is a subclass of the Drink
    elif(type_string is 'wine'):
        return Wine() # Wine is a subclass of the Drink
    elif(type_string is 'All'):
        return [Beer(), Wine()]
    raise Exception('invalid type_string : %s' % type_string)

위 코드는 사용자 입력을 받아 개체를 생성하고 반환하는 python 코드이다.

참고로 객체를 생성하고 반환하는 함수를 팩토리 메소드라 부르는 것 같다. 객체를 만드는 공장이라는 뜻이다.

추상화를 더하면 팩토리 메소드 패턴

객체 생성 함수에서 하나의 객체가 아니라 여러 종류의 객체를 반환하듯이, 로직이 다양한 객체 생성 함수를 가질 수 있게 하자.

객체지향 방법론을 따를 경우 객체 생성 부분을 추상 함수로 표현하면 된다.

from abc import ABC, abstractmethod

class DrinkStore(ABC):
    
    @abstractmethod
    def get_drink(self, type_string):
        raise NotImplementedError('Need a DrinkFactory!')
    
    def order(self, type_string):
        print(self.get_drink(type_string))
    def buffet(self):
        print(self.get_drink('All'))

위 코드에서 get_drink 부분이 추상 함수이다. 추상 함수를 가지고 있기 때문에 로직은 추상 클래스가 된다. 추상 클래스를 상속받아서 객체 생성 함수를 구현하면 된다. 그러면 로직부분이 공유되는 서로 다른 클래스가 만들어지게 된다.

class Bar(DrinkStore):
    def get_drink(self, type_string):
        if(type_string is 'beer'):
            return Beer() # Beer is a subclass of the Drink
        elif(type_string is 'wine'):
            return Wine() # Wine is a subclass of the Drink
        elif(type_string is 'All'):
            return [Beer(), Wine()]
        raise Exception('invalid type_string : %s' % type_string)

class CoffeeShop(DrinkStore):
    def get_drink(self, type_string):
        if(type_string is 'coffee'):
            return Coffee() # Coffee is a subclass of the Drink
        elif(type_string is 'blacktea'):
            return BlackTea() # BlackTea is a subclass of the Drink
        elif(type_string is 'All'):
            return [Coffee(), BlackTea()]

위 코드는 다양한 유형의 DrinkStore를 구현한 것이다. 객체 생성 함수만 구현하면 된다. 왜냐하면 그 외의 나머지 부분은 이미 구현이 되어 있기 때문이다.

추가로 추상 팩토리 메소드는?

객체 생성 함수 대신에 객체 생성 클래스를 이용할 때 추상 팩토리 메소드라고 한다.

요약

  • 상위 클래스에서 객체 생성 부분을 하위 클래스로 위임한다.
  • 객체 생성 함수와 로직을 분리시킬 수 있다.
  • 로직의 공유가 가능해진다.

Sponsored ( Powered by dclick )
구글 : '훙멍(화웨이 자체 OS 이름) 따라올테면 따라와봐'

화웨이에서 자체 OS '훙멍'화웨이 독자 개발 OS '훙멍'을 발표한 가운데 구글은...