Skip to content

Commit 2bdfe2a

Browse files
authored
Merge pull request faif#370 from yhay81/abstract_factory
Update abstract_factory more elaborate
2 parents 28e8b5f + 74eb634 commit 2bdfe2a

File tree

2 files changed

+50
-35
lines changed

2 files changed

+50
-35
lines changed

patterns/creational/abstract_factory.py

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,71 +31,85 @@
3131
"""
3232

3333
import random
34+
from typing import Type
3435

3536

36-
class PetShop:
37+
class Pet:
38+
def __init__(self, name: str) -> None:
39+
self.name = name
3740

38-
"""A pet shop"""
41+
def speak(self) -> None:
42+
raise NotImplementedError
3943

40-
def __init__(self, animal_factory=None):
41-
"""pet_factory is our abstract factory. We can set it at will."""
44+
def __str__(self) -> str:
45+
raise NotImplementedError
4246

43-
self.pet_factory = animal_factory
4447

45-
def show_pet(self):
46-
"""Creates and shows a pet using the abstract factory"""
48+
class Dog(Pet):
49+
def speak(self) -> None:
50+
print("woof")
51+
52+
def __str__(self) -> str:
53+
return f"Dog<{self.name}>"
54+
4755

48-
pet = self.pet_factory()
49-
print(f"We have a lovely {pet}")
50-
print(f"It says {pet.speak()}")
56+
class Cat(Pet):
57+
def speak(self) -> None:
58+
print("meow")
5159

60+
def __str__(self) -> str:
61+
return f"Cat<{self.name}>"
5262

53-
class Dog:
54-
def speak(self):
55-
return "woof"
5663

57-
def __str__(self):
58-
return "Dog"
64+
class PetShop:
65+
66+
"""A pet shop"""
5967

68+
def __init__(self, animal_factory: Type[Pet]) -> None:
69+
"""pet_factory is our abstract factory. We can set it at will."""
6070

61-
class Cat:
62-
def speak(self):
63-
return "meow"
71+
self.pet_factory = animal_factory
72+
73+
def buy_pet(self, name: str) -> Pet:
74+
"""Creates and shows a pet using the abstract factory"""
6475

65-
def __str__(self):
66-
return "Cat"
76+
pet = self.pet_factory(name)
77+
print(f"Here is your lovely {pet}")
78+
return pet
6779

6880

6981
# Additional factories:
7082

7183
# Create a random animal
72-
def random_animal():
84+
def random_animal(name: str) -> Pet:
7385
"""Let's be dynamic!"""
74-
return random.choice([Dog, Cat])()
86+
return random.choice([Dog, Cat])(name)
7587

7688

7789
# Show pets with various factories
78-
def main():
90+
def main() -> None:
7991
"""
8092
# A Shop that sells only cats
8193
>>> cat_shop = PetShop(Cat)
82-
>>> cat_shop.show_pet()
83-
We have a lovely Cat
84-
It says meow
94+
>>> pet = cat_shop.buy_pet("Lucy")
95+
Here is your lovely Cat<Lucy>
96+
>>> pet.speak()
97+
meow
8598
8699
# A shop that sells random animals
87100
>>> shop = PetShop(random_animal)
88-
>>> for i in range(3):
89-
... shop.show_pet()
101+
>>> for name in ["Max", "Jack", "Buddy"]:
102+
... pet = shop.buy_pet(name)
103+
... pet.speak()
90104
... print("=" * 20)
91-
We have a lovely Cat
92-
It says meow
105+
Here is your lovely Cat<Max>
106+
meow
93107
====================
94-
We have a lovely Dog
95-
It says woof
108+
Here is your lovely Dog<Jack>
109+
woof
96110
====================
97-
We have a lovely Dog
98-
It says woof
111+
Here is your lovely Dog<Buddy>
112+
woof
99113
====================
100114
"""
101115

tests/creational/test_abstract_factory.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ class TestPetShop(unittest.TestCase):
88
def test_dog_pet_shop_shall_show_dog_instance(self):
99
dog_pet_shop = PetShop(Dog)
1010
with patch.object(Dog, "speak") as mock_Dog_speak:
11-
dog_pet_shop.show_pet()
11+
pet = dog_pet_shop.buy_pet("")
12+
pet.speak()
1213
self.assertEqual(mock_Dog_speak.call_count, 1)

0 commit comments

Comments
 (0)