abstract-factory-pattern
TL; DR
- 상세한 서브 클래스를 정의하지 않고도 서로 관련이 있거나 독립적인 여러 객체 군을 생성하기 위한 인터페이스를 제공
활용성
- 객체가 생성되거나 구성, 표현되는 방식과 무관하게 시스템을 독립적으로 만들고자 할 때
- 여러 제품군 중 하나를 선택하여 시스템을 설정해야 하고, 한 번 구성한 제품군을 다른 것으로 대체할 수 있어야 할 때
- 제품에 대한 클래스 라이브러리를 제공하고, 그들의 구현이 아닌 인터페이스를 노출하고자 할 때
결과
- 장점
- 구체적인 클래스를 분리 : 응용 프로그램이 생성할 객체를 제어할 수 있음. 일반 프로그램은 구체적인 클래스를 사용하지 않고 추상 팩토리의 인터페이스를 통해 객체를 생성
- 제품군을 쉽게 대체 : 추상 팩토리를 사용하면 제품군을 쉽게 대체할 수 있음
- 제품군 사이의 일관성 : 제품군 내의 객체들이 함께 사용될 때 일관성을 유지할 수 있품
- 비용
- 새로운 제품 추가가 어려움 : 새로운 종류의 제품을 추가하려면 팩토리 클래스를 추가해야 함
구현
- 팩토리를 싱글톤으로 정의 : 하나의 제품군에 대해서는 하나의 팩토리만 있으면 됨
- 제품을 생성 : Abstract Factory 는 인터페이스만 정의하고, 구체 팩토리를 통해서 제품을 생성하도록 함
예시
from abc import ABC, abstractmethod
# 추상 제품 클래스들
class Chair(ABC):
@abstractmethod
def sit_on(self):
pass
class Table(ABC):
@abstractmethod
def put_on(self):
pass
# 구체적인 제품 클래스들
class ModernChair(Chair):
def sit_on(self):
return "모던 의자에 앉았습니다."
class VintageChair(Chair):
def sit_on(self):
return "빈티지 의자에 앉았습니다."
class ModernTable(Table):
def put_on(self):
return "모던 테이블 위에 물건을 올려놓았습니다."
class VintageTable(Table):
def put_on(self):
return "빈티지 테이블 위에 물건을 올려놓았습니다."
# 추상 팩토리 클래스
class FurnitureFactory(ABC):
@abstractmethod
def create_chair(self) -> Chair:
pass
@abstractmethod
def create_table(self) -> Table:
pass
# 구체적인 팩토리 클래스들
class ModernFurnitureFactory(FurnitureFactory):
def create_chair(self) -> Chair:
return ModernChair()
def create_table(self) -> Table:
return ModernTable()
class VintageFurnitureFactory(FurnitureFactory):
def create_chair(self) -> Chair:
return VintageChair()
def create_table(self) -> Table:
return VintageTable()
# 클라이언트 코드
def client_code(factory: FurnitureFactory) -> None:
chair = factory.create_chair()
table = factory.create_table()
print(chair.sit_on())
print(table.put_on())
# 사용 예시
if __name__ == "__main__":
print("모던 가구 생산:")
client_code(ModernFurnitureFactory())
print("\n빈티지 가구 생산:")
client_code(VintageFurnitureFactory())