참고 문서: https://github.com/faif/python-patterns
아래 글은 위 참고 문서를 토대로 만들어진 내용입니다.
서로 관련성이 있거나 독립적인 여러 객체들의 조합을 만들기 위한 인터페이스를 제공하는 패턴입니다.
참고 문서의 내용으로는 아래와 같이 설명합니다.
In Java and other languages, the Abstract Factory Pattern serves to provide an interface for
creating related/dependent objects without need to specify their
actual class.
자바와 다른 언어에서 추상 팩토리 패턴은 실제 클래스를 지정할 필요 없이 관련/의존 객체를 만들기 위한 인터페이스를 제공하는 역할을 한다.
예제로 Pet 그리고 Pet 을 상속 받는 Dog, Cat 을 기준으로 해보겠습니다.
import random
from typing import Type
class Pet:
def __init__(self, name: str) -> None:
self.name = name
def speak(self) -> None:
raise NotImplementedError
def __str__(self) -> str:
raise NotImplementedError
class Dog(Pet):
def speak(self) -> None:
print("woof")
def __str__(self) -> str:
return f"Dog<{self.name}>"
class Cat(Pet):
def speak(self) -> None:
print("meow")
def __str__(self) -> str:
return f"Cat<{self.name}>"
PetShop 이라는 클래스를 정의합시다.
class PetShop:
"""A pet shop"""
def __init__(self, animal_factory: Type[Pet]) -> None:
"""pet_factory is our abstract factory. We can set it at will."""
self.pet_factory = animal_factory
def buy_pet(self, name: str) -> Pet:
"""Creates and shows a pet using the abstract factory"""
pet = self.pet_factory(name)
print(f"Here is your lovely {pet}")
return pet
여기서 self.pet_factory 는 추상 팩토리가 되는 것입니다.
이제 위에 생성한 클래스들로 구체적인 사용 예를 들어봅시다.
import random
from typing import Type
class Pet:
def __init__(self, name: str) -> None:
self.name = name
def speak(self) -> None:
raise NotImplementedError
def __str__(self) -> str:
raise NotImplementedError
class Dog(Pet):
def speak(self) -> None:
print("woof")
def __str__(self) -> str:
return f"Dog<{self.name}>"
class Cat(Pet):
def speak(self) -> None:
print("meow")
def __str__(self) -> str:
return f"Cat<{self.name}>"
class PetShop:
"""A pet shop"""
def __init__(self, animal_factory: Type[Pet]) -> None:
"""pet_factory is our abstract factory. We can set it at will."""
self.pet_factory = animal_factory
def buy_pet(self, name: str) -> Pet:
"""Creates and shows a pet using the abstract factory"""
pet = self.pet_factory(name)
print(f"Here is your lovely {pet}")
return pet
# Additional factories:
# Create a random animal
def random_animal(name: str) -> Pet:
"""Let's be dynamic!"""
return random.choice([Dog, Cat])(name)
# Show pets with various factories
def main() -> None:
"""
# A Shop that sells only cats
>>> cat_shop = PetShop(Cat)
>>> pet = cat_shop.buy_pet("Lucy")
Here is your lovely Cat<Lucy>
>>> pet.speak()
meow
# A shop that sells random animals
>>> shop = PetShop(random_animal)
>>> for name in ["Max", "Jack", "Buddy"]:
... pet = shop.buy_pet(name)
... pet.speak()
... print("=" * 20)
Here is your lovely Cat<Max>
meow
====================
Here is your lovely Dog<Jack>
woof
====================
Here is your lovely Dog<Buddy>
woof
====================
"""
if __name__ == "__main__":
random.seed(1234) # for deterministic doctest outputs
shop = PetShop(random_animal)
import doctest
doctest.testmod()
위 코드를 보면 PetShop 은 Pet 의 클래스를 의존하고 있습니다.
PetShop 은 Pet 을 생성하고 있습니다.