Skip to content

Commit 6f1cfec

Browse files
author
Alan Tan
authored
Merge pull request #3 from faif/master
merge
2 parents 6a29d64 + 9ee9b44 commit 6f1cfec

File tree

4 files changed

+95
-56
lines changed

4 files changed

+95
-56
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ __pycache__
44
*.egg-info/
55
.tox/
66
venv
7+
.vscode/
8+
.python-version

patterns/behavioral/catalog.py

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,31 @@ class Catalog:
1212
parameter
1313
"""
1414

15-
def __init__(self, param):
15+
def __init__(self, param: str) -> None:
1616

1717
# dictionary that will be used to determine which static method is
1818
# to be executed but that will be also used to store possible param
1919
# value
20-
self._static_method_choices = {'param_value_1': self._static_method_1, 'param_value_2': self._static_method_2}
20+
self._static_method_choices = {
21+
"param_value_1": self._static_method_1,
22+
"param_value_2": self._static_method_2,
23+
}
2124

2225
# simple test to validate param value
2326
if param in self._static_method_choices.keys():
2427
self.param = param
2528
else:
26-
raise ValueError("Invalid Value for Param: {0}".format(param))
29+
raise ValueError(f"Invalid Value for Param: {param}")
2730

2831
@staticmethod
29-
def _static_method_1():
32+
def _static_method_1() -> None:
3033
print("executed method 1!")
3134

3235
@staticmethod
33-
def _static_method_2():
36+
def _static_method_2() -> None:
3437
print("executed method 2!")
3538

36-
def main_method(self):
39+
def main_method(self) -> None:
3740
"""will execute either _static_method_1 or _static_method_2
3841
3942
depending on self.param value
@@ -49,24 +52,27 @@ class CatalogInstance:
4952
parameter
5053
"""
5154

52-
def __init__(self, param):
53-
self.x1 = 'x1'
54-
self.x2 = 'x2'
55+
def __init__(self, param: str) -> None:
56+
self.x1 = "x1"
57+
self.x2 = "x2"
5558
# simple test to validate param value
5659
if param in self._instance_method_choices:
5760
self.param = param
5861
else:
59-
raise ValueError("Invalid Value for Param: {0}".format(param))
62+
raise ValueError(f"Invalid Value for Param: {param}")
6063

61-
def _instance_method_1(self):
62-
print("Value {}".format(self.x1))
64+
def _instance_method_1(self) -> None:
65+
print(f"Value {self.x1}")
6366

64-
def _instance_method_2(self):
65-
print("Value {}".format(self.x2))
67+
def _instance_method_2(self) -> None:
68+
print(f"Value {self.x2}")
6669

67-
_instance_method_choices = {'param_value_1': _instance_method_1, 'param_value_2': _instance_method_2}
70+
_instance_method_choices = {
71+
"param_value_1": _instance_method_1,
72+
"param_value_2": _instance_method_2,
73+
}
6874

69-
def main_method(self):
75+
def main_method(self) -> None:
7076
"""will execute either _instance_method_1 or _instance_method_2
7177
7278
depending on self.param value
@@ -81,25 +87,28 @@ class CatalogClass:
8187
parameter
8288
"""
8389

84-
x1 = 'x1'
85-
x2 = 'x2'
90+
x1 = "x1"
91+
x2 = "x2"
8692

87-
def __init__(self, param):
93+
def __init__(self, param: str) -> None:
8894
# simple test to validate param value
8995
if param in self._class_method_choices:
9096
self.param = param
9197
else:
92-
raise ValueError("Invalid Value for Param: {0}".format(param))
98+
raise ValueError(f"Invalid Value for Param: {param}")
9399

94100
@classmethod
95-
def _class_method_1(cls):
96-
print("Value {}".format(cls.x1))
101+
def _class_method_1(cls) -> None:
102+
print(f"Value {cls.x1}")
97103

98104
@classmethod
99-
def _class_method_2(cls):
100-
print("Value {}".format(cls.x2))
105+
def _class_method_2(cls) -> None:
106+
print(f"Value {cls.x2}")
101107

102-
_class_method_choices = {'param_value_1': _class_method_1, 'param_value_2': _class_method_2}
108+
_class_method_choices = {
109+
"param_value_1": _class_method_1,
110+
"param_value_2": _class_method_2,
111+
}
103112

104113
def main_method(self):
105114
"""will execute either _class_method_1 or _class_method_2
@@ -116,28 +125,32 @@ class CatalogStatic:
116125
parameter
117126
"""
118127

119-
def __init__(self, param):
128+
def __init__(self, param: str) -> None:
120129
# simple test to validate param value
121130
if param in self._static_method_choices:
122131
self.param = param
123132
else:
124-
raise ValueError("Invalid Value for Param: {0}".format(param))
133+
raise ValueError(f"Invalid Value for Param: {param}")
125134

126135
@staticmethod
127-
def _static_method_1():
136+
def _static_method_1() -> None:
128137
print("executed method 1!")
129138

130139
@staticmethod
131-
def _static_method_2():
140+
def _static_method_2() -> None:
132141
print("executed method 2!")
133142

134-
_static_method_choices = {'param_value_1': _static_method_1, 'param_value_2': _static_method_2}
143+
_static_method_choices = {
144+
"param_value_1": _static_method_1,
145+
"param_value_2": _static_method_2,
146+
}
135147

136-
def main_method(self):
148+
def main_method(self) -> None:
137149
"""will execute either _static_method_1 or _static_method_2
138150
139151
depending on self.param value
140152
"""
153+
141154
self._static_method_choices[self.param].__get__(None, self.__class__)()
142155

143156

@@ -163,4 +176,5 @@ def main():
163176

164177
if __name__ == "__main__":
165178
import doctest
179+
166180
doctest.testmod()

patterns/creational/borg.py

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,41 @@
2525
https://github.com/onetwopunch/pythonDbTemplate/blob/master/database.py
2626
2727
*References:
28-
https://fkromer.github.io/python-pattern-references/design/#singleton
28+
- https://fkromer.github.io/python-pattern-references/design/#singleton
29+
- https://learning.oreilly.com/library/view/python-cookbook/0596001673/ch05s23.html
30+
- http://www.aleax.it/5ep.html
2931
3032
*TL;DR
3133
Provides singleton-like behavior sharing state between instances.
3234
"""
3335

3436

3537
class Borg:
36-
__shared_state = {}
38+
_shared_state = {}
3739

3840
def __init__(self):
39-
self.__dict__ = self.__shared_state
40-
self.state = 'Init'
41-
42-
def __str__(self):
43-
return self.state
41+
self.__dict__ = self._shared_state
4442

4543

4644
class YourBorg(Borg):
47-
pass
4845

46+
def __init__(self, state=None):
47+
super().__init__()
48+
if state:
49+
self.state = state
50+
else:
51+
# initiate the first instance with default state
52+
if not hasattr(self, 'state'):
53+
self.state = 'Init'
54+
55+
def __str__(self):
56+
return self.state
57+
4958

5059
def main():
5160
"""
52-
>>> rm1 = Borg()
53-
>>> rm2 = Borg()
61+
>>> rm1 = YourBorg()
62+
>>> rm2 = YourBorg()
5463
5564
>>> rm1.state = 'Idle'
5665
>>> rm2.state = 'Running'
@@ -73,15 +82,25 @@ def main():
7382
>>> rm1 is rm2
7483
False
7584
76-
# Shared state is also modified from a subclass instance `rm3`
85+
# New instances also get the same shared state
7786
>>> rm3 = YourBorg()
7887
7988
>>> print('rm1: {0}'.format(rm1))
80-
rm1: Init
89+
rm1: Zombie
8190
>>> print('rm2: {0}'.format(rm2))
82-
rm2: Init
91+
rm2: Zombie
92+
>>> print('rm3: {0}'.format(rm3))
93+
rm3: Zombie
94+
95+
# A new instance can explicitly change the state during creation
96+
>>> rm4 = YourBorg('Running')
97+
98+
>>> print('rm4: {0}'.format(rm4))
99+
rm4: Running
100+
101+
# Existing instances reflect that change as well
83102
>>> print('rm3: {0}'.format(rm3))
84-
rm3: Init
103+
rm3: Running
85104
"""
86105

87106

patterns/structural/composite.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,37 @@
2626
Describes a group of objects that is treated as a single instance.
2727
"""
2828

29+
from abc import ABC, abstractmethod
30+
from typing import List
2931

30-
class Graphic:
31-
def render(self):
32-
raise NotImplementedError("You should implement this.")
32+
33+
class Graphic(ABC):
34+
@abstractmethod
35+
def render(self) -> None:
36+
raise NotImplementedError("You should implement this!")
3337

3438

3539
class CompositeGraphic(Graphic):
36-
def __init__(self):
37-
self.graphics = []
40+
def __init__(self) -> None:
41+
self.graphics: List[Graphic] = []
3842

39-
def render(self):
43+
def render(self) -> None:
4044
for graphic in self.graphics:
4145
graphic.render()
4246

43-
def add(self, graphic):
47+
def add(self, graphic: Graphic) -> None:
4448
self.graphics.append(graphic)
4549

46-
def remove(self, graphic):
50+
def remove(self, graphic: Graphic) -> None:
4751
self.graphics.remove(graphic)
4852

4953

5054
class Ellipse(Graphic):
51-
def __init__(self, name):
55+
def __init__(self, name: str) -> None:
5256
self.name = name
5357

54-
def render(self):
55-
print("Ellipse: {}".format(self.name))
58+
def render(self) -> None:
59+
print(f"Ellipse: {self.name}")
5660

5761

5862
def main():

0 commit comments

Comments
 (0)