责任链模式

责任链模式用于让多个对象来处理单个请求时,或者用于预先不知道应该由哪个对象来处理某个特定请求时候:

  • 一开始将请求发送给链中的第一个对象
  • 对象决定是否处理该请求
  • 对象将请求转发给下一个对象
  • 重复该过程,直到到达链尾

java的servlet过滤器是在一个HTTP请求到达目标处理程序之前的一些代码片段。有一个过滤器链,其中每个过滤器执行一个不同动作(用户身份验证,日志等),并且将请求转发给下一个过滤器直到链结束。如果发生错误就跳出处理流程。

这一模式的价值在于解耦,客户端与所有处理程序之间不再是多对多的关系,客户端只需要知道如何与链的起始节点进行通信。松耦合。

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
class Event:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
class Widget:
"""Docstring for Widget. """
def __init__(self, parent=None):
self.parent = parent
def handle(self, event):
handler = 'handle_{}'.format(event)
if hasattr(self, handler):
method = getattr(self, handler)
method(event)
elif self.parent:
self.parent.handle(event)
elif hasattr(self, 'handle_default'):
self.handle_default(event)
class MainWindow(Widget):
def handle_close(self, event):
print('MainWindow: {}'.format(event))
def handle_default(self, event):
print('MainWindow: Default {}'.format(event))
class SendDialog(Widget):
def handle_paint(self, event):
print('SendDialog: {}'.format(event))
class MsgText(Widget):
def handle_down(self, event):
print('MsgText: {}'.format(event))
def main():
mw = MainWindow()
sd = SendDialog(mw) # parent是mw
msg = MsgText(sd)
for e in ('down', 'paint', 'unhandled', 'close'):
evt = Event(e)
print('\nSending event -{}- to MainWindow'.format(evt))
mw.handle(evt)
print('Sending event -{}- to SendDialog'.format(evt))
sd.handle(evt)
print('Sending event -{}- to MsgText'.format(evt))
msg.handle(evt)
if __name__ == "__main__":
main()

命令模式

命令设计模式使得将一个操作(撤销,重做,复制,粘贴)封装成一个对象。意味着创建一个类,包含实现这个操作所需要的所有逻辑和方法。这样调用命令的对象与知道如何执行命令的对象解耦。撤销操作。

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
import os
class RenameFile:
def __init__(self, path_src, path_dest):
""" 在init里保存一些必要信息,比如undo需要的老的和新的文件名 """
self.src, self.dest = path_src, path_dest
def execute(self, verbose=False):
if verbose:
print("[renaming '{}' to '{}']".format(self.src, self.dest))
os.rename(self.src, self.dest)
def undo(self, verbose=False):
if verbose:
print("[renaming '{}' back to '{}']".format(self.dest, self.src))
os.rename(self.dest, self.src)
def delete_file(path, verbose=False):
if verbose:
print("deleting file '{}".format(path))
os.remove(path)
class CreateFile:
def __init__(self, path, txt='hello world\n'):
self.path, self.txt = path, txt
def execute(self, verbose=False):
if verbose:
print("[creating file '{}']".format(self.path))
with open(self.path, mode='w', encoding='utf-8') as out_file:
out_file.write(self.txt)
def undo(self):
delete_file(self.path)
class ReadFile:
def __init__(self, path):
self.path = path
def execute(self, verbose=False):
if verbose:
print("[reading file '{}']".format(self.path))
with open(self.path, mode='r', encoding='utf-8') as in_file:
print(in_file.read(), end='')
def main():
orig_name, new_name = 'file1', 'file2'
commands = []
for cmd in CreateFile(orig_name), ReadFile(orig_name), RenameFile(orig_name, new_name):
commands.append(cmd)
[c.execute() for c in commands]
answer = input('reverse the executed commands? [y/n] ')
if answer not in 'yY':
print("the result is {}".format(new_name))
exit()
for c in reversed(commands):
try:
c.undo() # 执行undo
except AttributeError:
pass
main()

使用命令模式可以将一个操作封装成一个对象,这样:

  • 可以在任何时候执行一个命令,而并不一定是命令创建时候
  • 执行一个命令的客户端代码并不需要知道命令的任何实现细节
  • 可以对命令进行分组,并按照一定顺序执行

有助于实现事务,可以将多个命令组合成事务,这样一个失败了,所有操作都回滚撤销,这样就是一个事务。

观察者模式

观察者模式描述单个对象(发布者)与一个或者多个对象(订阅者)之间的发布-订阅关系。MVC中,发布者是模型,订阅者时视图。信息聚合订阅RSS也是。也是一种关注点分离的思想,降低发布者与订阅者之间的耦合度。

RabbitMQ可以为应用添加异步消息支持,这样就可以在Python应用者实现发布-订阅模式,也就是观察者设计模式。

事件驱动系统是另一个可以使用观察者模式的例子,监听者监听特定事件。

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
class Publisher:
def __init__(self):
self.observers = []
def add(self, observer):
if observer not in self.observers:
self.observers.append(observer)
else:
print('Failed to add : {}').format(observer)
def remove(self, observer):
try:
self.observers.remove(observer)
except ValueError:
print('Failed to remove : {}').format(observer)
def notify(self):
[o.notify_by(self) for o in self.observers]
class DefaultFormatter(Publisher):
def __init__(self, name):
super().__init__()
self.name = name
self._data = 0
def __str__(self):
return "{}: '{}' has data = {}".format(
type(self).__name__, self.name, self._data)
@property
def data(self):
return self._data
@data.setter
def data(self, new_value):
"""
设置data的时候就是发布数据,然后会通知所有订阅者
"""
try:
self._data = int(new_value)
except ValueError as e:
print('Error: {}'.format(e))
else:
self.notify() # data 在被合法赋值以后会执行notify
class HexFormatter:
""" 订阅者 """
def notify_by(self, publisher):
print("{}: '{}' has now hex data = {}".format(
type(self).__name__, publisher.name, hex(publisher.data)))
class BinaryFormatter:
""" 订阅者 """
def notify_by(self, publisher):
print("{}: '{}' has now bin data = {}".format(
type(self).__name__, publisher.name, bin(publisher.data)))
if __name__ == "__main__":
df = DefaultFormatter('test1')
print(df)
print()
hf = HexFormatter()
df.add(hf)
df.data = 3
print(df)
print()
bf = BinaryFormatter()
df.add(bf)
df.data = 21
print(df)

状态模式

面向对象编程着力于在对象交互时候改变它们的状态。有限状态机是一个有用的状态转换建模工具。状态模式就是应用到一个特定软件工程问题的状态机。

事件驱动系统也是一个例子,在一个事件驱动系统中,从一个状态转换到另一个状态会触发一个事件。状态设计模式解决的是一定上下文中无限数量状态的完全封装,从而实现更好的可维护性和灵活性。

state_machine库在建立状态机方面非常好用

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
97
98
99
100
101
# 先装下pip3 install state_machine
from state_machine import (
acts_as_state_machine, State, Event, before, after, InvalidStateTransition
)
@acts_as_state_machine
class Process:
# 先来定义状态机的状态 states
created = State(initial=True) # 初始状态
waiting = State()
running = State()
terminated = State()
blocked = State()
swapped_out_waiting = State()
swapped_out_blocked = State()
# 再定义状态机的转移 transitions
wait = Event(from_states=(created, running, blocked,
swapped_out_waiting), to_state=waiting)
run = Event(from_states=waiting, to_state=running)
terminate = Event(from_states=running, to_state=terminated)
block = Event(from_states=(running, swapped_out_blocked),
to_state=blocked)
swap_wait = Event(from_states=waiting, to_state=swapped_out_waiting)
swap_block = Event(from_states=blocked, to_state=swapped_out_blocked)
def __init__(self, name):
self.name = name
# The state_machine module provides us with the @before and @after
# decorators that can be used to execute actions before or after a
# transition occurs, respectfully.
@after('wait')
def wait_info(self):
print('{} entered waiting mode'.format(self.name))
@after('run')
def run_info(self):
print('{} is running'.format(self.name))
@before('terminate')
def terminate_info(self):
print('{} terminated'.format(self.name))
@after('block')
def block_info(self):
print('{} is blocked'.format(self.name))
@after('swap_wait')
def swap_wait_info(self):
print('{} is swapped out and waiting'.format(self.name))
@after('swap_block')
def swap_block_info(self):
print('{} is swapped out and blocked'.format(self.name))
def transition(process, event, event_name):
"""
Args:
process (Process obj):
event (Event obj): wait, run, terminate...
event_name (str): name of event
"""
try:
event()
except InvalidStateTransition:
print('Error: transition of {} from {} to {} failed'.format(
process.name, process.current_state, event_name))
def state_info(process):
""" 当前状态机的状态 """
print('state of {}: {}'.format(process.name, process.current_state))
if __name__ == "__main__":
RUNNING = 'running'
WAITING = 'waiting'
BLOCKED = 'blocked'
TERMINATED = 'terminated'
p1, p2 = Process('process1'), Process('process2')
[state_info(p) for p in (p1, p2)]
print()
transition(p1, p1.wait, WAITING)
transition(p2, p2.terminate, TERMINATED)
[state_info(p) for p in (p1, p2)]
print()
transition(p1, p1.run, RUNNING)
transition(p2, p2.wait, WAITING)
[state_info(p) for p in (p1, p2)]
print()
transition(p2, p2.run, RUNNING)
[state_info(p) for p in (p1, p2)]
print()
[transition(p, p.block, BLOCKED) for p in (p1, p2)]
[state_info(p) for p in (p1, p2)]
print()
[transition(p, p.terminate, TERMINATED) for p in (p1, p2)]
[state_info(p) for p in (p1, p2)]

状态模式是一个或者多个有限状态机的实现,状态机有两个部分,状态和转换。

策略模式

策略模式鼓励使用多种算法来解决一个问题,运行的时候透明的切换算法。Python中的sorted()list.sort()时策略模式的例子,都接受key,这个参数本质上是实现了一个排序策略的函数的名称,让客户端决定如何对一个数据结构中的元素进行排序。策略模式的另一个应用是创建不同的样式表现,为了实现可移植性或者动态地改变数据的表现。

1
2
3
4
5
6
7
8
9
10
11
def f1(seq):
pass
def f2(seq):
pass
def f(seq):
if len(seq) >= threshold_value: # 大于某个阈值
f1(seq) # 在数量较多时候具有良好的效率
else:
f2(seq)

模板模式

模版设计模式关注的时消除代码冗余,无需改变算法结构就能重新定义一个算法的某些部分。

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
from cowpy import cow
def dots_style(msg):
msg = msg.capitalize()
msg = '.' * 10 + msg + '.' * 10
return msg
def admire_style(msg):
msg = msg.upper()
return '!'.join(msg)
def cow_style(msg):
msg = cow.milk_random_cow(msg)
return msg
def generate_banner(msg, style=dots_style):
print('-- start of banner --')
print(style(msg))
print('-- end of banner --\n\n')
def main():
msg = 'happy coding'
[generate_banner(msg, style) for style in (dots_style, admire_style,
cow_style)]
if __name__ == "__main__":
main()

子类重写模版类的现有方法