- Notifications
You must be signed in to change notification settings - Fork 7k
/
Copy pathabstract_factory.py
96 lines (67 loc) · 2.41 KB
/
abstract_factory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""
*What is this pattern about?
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.
The idea is to abstract the creation of objects depending on business
logic, platform choice, etc.
In Python, the interface we use is simply a callable, which is "builtin" interface
in Python, and in normal circumstances we can simply use the class itself as
that callable, because classes are first class objects in Python.
*What does this example do?
This particular implementation abstracts the creation of a pet and
does so depending on the factory we chose (Dog or Cat, or random_animal)
This works because both Dog/Cat and random_animal respect a common
interface (callable for creation and .speak()).
Now my application can create pets abstractly and decide later,
based on my own criteria, dogs over cats.
*Where is the pattern used practically?
*References:
https://sourcemaking.com/design_patterns/abstract_factory
http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/
*TL;DR
Provides a way to encapsulate a group of individual factories.
"""
importrandom
fromtypingimportType
classPet:
def__init__(self, name: str) ->None:
self.name=name
defspeak(self) ->None:
raiseNotImplementedError
def__str__(self) ->str:
raiseNotImplementedError
classDog(Pet):
defspeak(self) ->None:
print("woof")
def__str__(self) ->str:
returnf"Dog<{self.name}>"
classCat(Pet):
defspeak(self) ->None:
print("meow")
def__str__(self) ->str:
returnf"Cat<{self.name}>"
classPetShop:
"""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
defbuy_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}")
returnpet
# Show pets with various factories
defmain() ->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
"""
if__name__=="__main__":
shop=PetShop(random_animal)
importdoctest
doctest.testmod()