Skip to content

Commit 480905b

Browse files
committed
Merge branch 'washwash-master'
2 parents 07fe6ec + dd5d67a commit 480905b

File tree

5 files changed

+195
-3
lines changed

5 files changed

+195
-3
lines changed

‎3-tier.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ class Data(object):
1212
}
1313

1414
def__get__(self, obj, klas):
15-
print("(Fetching from Data Store)")
15+
print("(Fetching from Data Store)")
1616
return{'products': self.products}
1717

1818

1919
classBusinessLogic(object):
20-
2120
""" Business logic holding data store instances """
2221

2322
data=Data()

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Current Patterns:
2525
|[decorator](decorator.py)| wrap functionality with other functionality in order to affect outputs |
2626
|[facade](facade.py)| use one class as an API to a number of others |
2727
|[factory_method](factory_method.py)| delegate a specialized function/method to create instances |
28+
|[front_controller](front_controller.py)| single handler requests coming to the application |
2829
|[flyweight](flyweight.py)| transparently reuse existing instances of objects with similar/identical state |
2930
|[graph_search](graph_search.py)| (graphing algorithms, not design patterns) |
3031
|[lazy_evaluation](lazy_evaluation.py)| lazily-evaluated property pattern in Python |
@@ -36,6 +37,7 @@ Current Patterns:
3637
|[prototype](prototype.py)| use a factory and clones of a prototype for new instances (if instantiation is expensive) |
3738
|[proxy](proxy.py)| an object funnels operations to something else |
3839
|[publish_subscribe](publish_subscribe.py)| a source syndicates events/data to 0+ registered listeners |
40+
|[specification](specification.py)| business rules can be recombined by chaining the business rules together using boolean logic |
3941
|[state](state.py)| logic is org'd into a discrete number of potential states and the next state that can be transitioned to |
4042
|[strategy](strategy.py)| selectable operations over the same data |
4143
|[template](template.py)| an object imposes a structure but takes pluggable components |

‎adapter.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ def make_noise(self, octane_level):
3737

3838

3939
classAdapter(object):
40-
4140
"""
4241
Adapts an object by replacing methods.
4342
Usage:

‎front_controller.py‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
@author: Gordeev Andrey <[email protected]>
6+
The controller provides a centralized entry point that controls and manages
7+
request handling.
8+
"""
9+
10+
11+
classMobileView(object):
12+
defshow_index_page(self):
13+
print('Displaying mobile index page')
14+
15+
16+
classTabletView(object):
17+
defshow_index_page(self):
18+
print('Displaying tablet index page')
19+
20+
21+
classDispatcher(object):
22+
def__init__(self):
23+
self.mobile_view=MobileView()
24+
self.tablet_view=TabletView()
25+
26+
defdispatch(self, request):
27+
ifrequest.type==Request.mobile_type:
28+
self.mobile_view.show_index_page()
29+
elifrequest.type==Request.tablet_type:
30+
self.tablet_view.show_index_page()
31+
else:
32+
print('cant dispatch the request')
33+
34+
35+
classRequestController(object):
36+
""" front controller """
37+
def__init__(self):
38+
self.dispatcher=Dispatcher()
39+
40+
defdispatch_request(self, request):
41+
ifisinstance(request, Request):
42+
self.dispatcher.dispatch(request)
43+
else:
44+
print('request must be a Request object')
45+
46+
47+
classRequest(object):
48+
""" request """
49+
50+
mobile_type='mobile'
51+
tablet_type='tablet'
52+
53+
def__init__(self, request):
54+
self.type=None
55+
request=request.lower()
56+
ifrequest==self.mobile_type:
57+
self.type=self.mobile_type
58+
elifrequest==self.tablet_type:
59+
self.type=self.tablet_type
60+
61+
62+
if__name__=='__main__':
63+
front_controller=RequestController()
64+
front_controller.dispatch_request(Request('mobile'))
65+
front_controller.dispatch_request(Request('tablet'))
66+
67+
front_controller.dispatch_request(Request('desktop'))
68+
front_controller.dispatch_request('mobile')
69+
70+
71+
### OUTPUT ###
72+
# Displaying mobile index page
73+
# Displaying tablet index page
74+
# cant dispatch the request
75+
# request must be a Request object

‎specification.py‎

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
@author: Gordeev Andrey <[email protected]>
6+
7+
Specification provide recombination business logic by
8+
chaining together using boolean logic
9+
"""
10+
11+
fromabcimportabstractmethod
12+
13+
14+
classSpecification(object):
15+
16+
defand_specification(self, candidate):
17+
raiseNotImplementedError()
18+
19+
defor_specification(self, candidate):
20+
raiseNotImplementedError()
21+
22+
defnot_specification(self):
23+
raiseNotImplementedError()
24+
25+
@abstractmethod
26+
defis_satisfied_by(self, candidate):
27+
pass
28+
29+
30+
classCompositeSpecification(Specification):
31+
@abstractmethod
32+
defis_satisfied_by(self, candidate):
33+
pass
34+
35+
defand_specification(self, candidate):
36+
returnAndSpecification(self, candidate)
37+
38+
defor_specification(self, candidate):
39+
returnOrSpecification(self, candidate)
40+
41+
defnot_specification(self):
42+
returnNotSpecification(self)
43+
44+
45+
classAndSpecification(CompositeSpecification):
46+
_one=Specification()
47+
_other=Specification()
48+
49+
def__init__(self, one, other):
50+
self._one=one
51+
self._other=other
52+
53+
defis_satisfied_by(self, candidate):
54+
returnbool(self._one.is_satisfied_by(candidate) and
55+
self._other.is_satisfied_by(candidate))
56+
57+
58+
classOrSpecification(CompositeSpecification):
59+
_one=Specification()
60+
_other=Specification()
61+
62+
def__init__(self, one, other):
63+
self._one=one
64+
self._other=other
65+
66+
defis_satisfied_by(self, candidate):
67+
returnbool(self._one.is_satisfied_by(candidate) or
68+
self._other.is_satisfied_by(candidate))
69+
70+
71+
classNotSpecification(CompositeSpecification):
72+
_wrapped=Specification()
73+
74+
def__init__(self, wrapped):
75+
self._wrapped=wrapped
76+
77+
defis_satisfied_by(self, candidate):
78+
returnbool(notself._wrapped.is_satisfied_by(candidate))
79+
80+
81+
classUser(object):
82+
83+
def__init__(self, super_user=False):
84+
self.super_user=super_user
85+
86+
87+
classUserSpecification(CompositeSpecification):
88+
89+
defis_satisfied_by(self, candidate):
90+
returnisinstance(candidate, User)
91+
92+
93+
classSuperUserSpecification(CompositeSpecification):
94+
95+
defis_satisfied_by(self, candidate):
96+
returngetattr(candidate, 'super_user', False)
97+
98+
99+
if__name__=='__main__':
100+
print('Specification')
101+
andrey=User()
102+
ivan=User(super_user=True)
103+
vasiliy='not User instance'
104+
105+
root_specification=UserSpecification().\
106+
and_specification(SuperUserSpecification())
107+
108+
print(root_specification.is_satisfied_by(andrey))
109+
print(root_specification.is_satisfied_by(ivan))
110+
print(root_specification.is_satisfied_by(vasiliy))
111+
112+
113+
### OUTPUT ###
114+
# Specification
115+
# False
116+
# True
117+
# False

0 commit comments

Comments
(0)