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
import doctest
doctest.testmod()
原文地址:python-patterns/abstract_factory.py at master · faif/python-patterns · GitHub