设计模式python总结

代码: https://github.com/youngsterxyf/mpdp-code

创建型

1. 工厂模式

场景:
客户端1可以请求一个对象,而无需知道这个对象来自哪里
创建对象的代码和使用对象的代码解耦
我们执行单个函数,传入一个参数(提供信息表明我们想要什么),但
并不要求知道任何关于对象如何实现以及对象来自哪里的细节。

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
import xml.etree.ElementTree as etree
import json


class JSONConnector:

def __init__(self, filepath):
self.data = dict()
with open(filepath, mode='r', encoding='utf-8') as f:
self.data = json.load(f)

@property
def parsed_data(self):
return self.data


class XMLConnector:

def __init__(self, filepath):
self.tree = etree.parse(filepath)

@property
def parsed_data(self):
return self.tree


def connection_factory(filepath):
if filepath.endswith('json'):
connector = JSONConnector
elif filepath.endswith('xml'):
connector = XMLConnector
else:
raise ValueError('Cannot connect to {}'.format(filepath))
return connector(filepath)


def connect_to(filepath):
factory = None
try:
factory = connection_factory(filepath)
except ValueError as ve:
print(ve)
return factory


def main():
sqlite_factory = connect_to('data/person.sq3')
print()

xml_factory = connect_to('data/person.xml')
xml_data = xml_factory.parsed_data
liars = xml_data.findall(".//{}[{}='{}']".format('person',
'lastName', 'Liar'))
print('found: {} persons'.format(len(liars)))
for liar in liars:
print('first name: {}'.format(liar.find('firstName').text))
print('last name: {}'.format(liar.find('lastName').text))
[print('phone number ({})'.format(p.attrib['type']),
p.text) for p in liar.find('phoneNumbers')]

print()

json_factory = connect_to('data/donut.json')
json_data = json_factory.parsed_data
print('found: {} donuts'.format(len(json_data)))
for donut in json_data:
print('name: {}'.format(donut['name']))
print('price: ${}'.format(donut['ppu']))
[print('topping: {} {}'.format(t['id'], t['type'])) for t in donut['topping']]

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
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
102
103
104
105
106
107
class Frog:

def __init__(self, name):
self.name = name

def __str__(self):
return self.name

def interact_with(self, obstacle):
print('{} the Frog encounters {} and {}!'.format(self,
obstacle, obstacle.action()))


class Bug:

def __str__(self):
return 'a bug'

def action(self):
return 'eats it'


class FrogWorld:

def __init__(self, name):
print(self)
self.player_name = name

def __str__(self):
return '\n\n\t------ Frog World ———'

def make_character(self):
return Frog(self.player_name)

def make_obstacle(self):
return Bug()


class Wizard:

def __init__(self, name):
self.name = name

def __str__(self):
return self.name

def interact_with(self, obstacle):
print('{} the Wizard battles against {} and {}!'.format(self, obstacle, obstacle.action()))


class Ork:

def __str__(self):
return 'an evil ork'

def action(self):
return 'kills it'


class WizardWorld:

def __init__(self, name):
print(self)
self.player_name = name

def __str__(self):
return '\n\n\t------ Wizard World ———'

def make_character(self):
return Wizard(self.player_name)

def make_obstacle(self):
return Ork()


class GameEnvironment:

def __init__(self, factory):
self.hero = factory.make_character()
self.obstacle = factory.make_obstacle()

def play(self):
self.hero.interact_with(self.obstacle)


def validate_age(name):
try:
age = input('Welcome {}. How old are you? '.format(name))
age = int(age)
except ValueError as err:
print("Age {} is invalid, please try \
again…".format(age))
return (False, age)
return (True, age)


def main():
name = input("Hello. What's your name? ")
valid_input = False
while not valid_input:
valid_input, age = validate_age(name)
game = FrogWorld if age < 18 else WizardWorld
environment = GameEnvironment(game(name))
environment.play()

if __name__ == '__main__':
main()

2. 建造者模式

场景:
即使存在多种汉堡包(经典款、奶酪汉堡包等)和不同 包装(小盒子、中等大小盒子等),准备一个汉堡包及打包(盒子或纸袋)的流程都是相同的
指挥者和建造者分开
EngineerBuilder 分开

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
# coding: utf-8
class Computer:

def __init__(self, serial_number):
self.serial = serial_number
self.memory = None # 单位为GB
self.hdd = None # 单位为GB
self.gpu = None

def __str__(self):
info = ('Memory: {}GB'.format(self.memory),
'Hard Disk: {}GB'.format(self.hdd),
'Graphics Card: {}'.format(self.gpu))
return '\n'.join(info)


class ComputerBuilder:

def __init__(self):
self.computer = Computer('AG23385193')

def configure_memory(self, amount):
self.computer.memory = amount

def configure_hdd(self, amount):
self.computer.hdd = amount

def configure_gpu(self, gpu_model):
self.computer.gpu = gpu_model


class HardwareEngineer:

def __init__(self):
self.builder = None

def construct_computer(self, memory, hdd, gpu):
self.builder = ComputerBuilder()
[step for step in (self.builder.configure_memory(memory),
self.builder.configure_hdd(hdd),
self.builder.configure_gpu(gpu))]

@property
def computer(self):
return self.builder.computer


def main():
engineer = HardwareEngineer()
engineer.construct_computer(hdd=500, memory=8, gpu='GeForce GTX 650 Ti')
computer = engineer.computer
print(computer)

if __name__ == '__main__':
main()

3.原型模式

结构型

1. 适配器模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Adapter:
def __init__(self, obj, adapted_methods):
self.obj = obj
self.__dict__.update(adapted_methods)
def __str__(self):
return str(self.obj)

def main():
objects = [Computer('Asus')]
synth = Synthesizer('moog')
objects.append(Adapter(synth, dict(execute=synth.play)))
human = Human('Bob')
objects.append(Adapter(human, dict(execute=human.speak))) 12
for i in objects:
print('{} {}'.format(str(i), i.execute()))

2.修饰器模式

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
# coding: utf-8

import functools


def memoize(fn):
known = dict()

@functools.wraps(fn)
def memoizer(*args):
if args not in known:
known[args] = fn(*args)
return known[args]

return memoizer


@memoize
def nsum(n):
'''返回前n个数字的和'''
assert(n >= 0), 'n must be >= 0'
return 0 if n == 0 else n + nsum(n-1)


@memoize
def fibonacci(n):
'''返回斐波那契数列的第n个数'''
assert(n >= 0), 'n must be >= 0'
return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2)

if __name__ == '__main__':
from timeit import Timer
measure = [{'exec': 'fibonacci(100)', 'import': 'fibonacci',
'func': fibonacci}, {'exec': 'nsum(200)', 'import': 'nsum',
'func': nsum}]
for m in measure:
t = Timer('{}'.format(m['exec']), 'from __main__ import \
{}'.format(m['import']))
print('name: {}, doc: {}, executing: {}, time: \
{}'.format(m['func'].__name__, m['func'].__doc__,
m['exec'], t.timeit()))

3.外观模式

我们并不想把这种复杂性暴露给客户端。外观设计模式有助于隐藏 系统的内部复杂性,并通过一个简化的接口向客户端暴露必要的部分

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# coding: utf-8

from enum import Enum
from abc import ABCMeta, abstractmethod

State = Enum('State', 'new running sleeping restart zombie')


class User:
pass


class Process:
pass


class File:
pass


class Server(metaclass=ABCMeta):

@abstractmethod
def __init__(self):
pass

def __str__(self):
return self.name

@abstractmethod
def boot(self):
pass

@abstractmethod
def kill(self, restart=True):
pass


class FileServer(Server):

def __init__(self):
'''初始化文件服务进程要求的操作'''
self.name = 'FileServer'
self.state = State.new

def boot(self):
print('booting the {}'.format(self))
'''启动文件服务进程要求的操作'''
self.state = State.running

def kill(self, restart=True):
print('Killing {}'.format(self))
'''杀死文件服务进程要求的操作'''
self.state = State.restart if restart else State.zombie

def create_file(self, user, name, permissions):
'''检查访问权限的有效性、用户权限,等等'''

print("trying to create the file '{}' for user '{}' with permissions {}".format(name, user, permissions))


class ProcessServer(Server):

def __init__(self):
'''初始化进程服务进程要求的操作'''
self.name = 'ProcessServer'
self.state = State.new

def boot(self):
print('booting the {}'.format(self))
'''启动进程服务进程要求的操作'''
self.state = State.running

def kill(self, restart=True):
print('Killing {}'.format(self))
'''杀死进程服务进程要求的操作'''
self.state = State.restart if restart else State.zombie

def create_process(self, user, name):
'''检查用户权限、生成PID,等等'''

print("trying to create the process '{}' for user '{}'".format(name, user))


class WindowServer:
pass


class NetworkServer:
pass


class OperatingSystem:

'''外观'''

def __init__(self):
self.fs = FileServer()
self.ps = ProcessServer()

def start(self):
[i.boot() for i in (self.fs, self.ps)]

def create_file(self, user, name, permissions):
return self.fs.create_file(user, name, permissions)

def create_process(self, user, name):
return self.ps.create_process(user, name)


def main():
os = OperatingSystem()
os.start()
os.create_file('foo', 'hello', '-rw-r-r')
os.create_process('bar', 'ls /tmp')

if __name__ == '__main__':
main()

4. MVC模式

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
quotes = ('A man is not complete until he is married. Then he is finished.',
'As I said before, I never repeat myself.',
'Behind a successful man is an exhausted woman.',
'Black holes really suck...', 'Facts are stubborn things.')


class QuoteModel:

def get_quote(self, n):
try:
value = quotes[n]
except IndexError as err:
value = 'Not found!'
return value


class QuoteTerminalView:

def show(self, quote):
print('And the quote is: "{}"'.format(quote))

def error(self, msg):
print('Error: {}'.format(msg))

def select_quote(self):
return input('Which quote number would you like to see?')


class QuoteTerminalController:

def __init__(self):
self.model = QuoteModel()
self.view = QuoteTerminalView()

def run(self):
valid_input = False
while not valid_input:
n = self.view.select_quote()
try:
n = int(n)
except ValueError as err:
self.view.error("Incorrect index '{}'".format(n))
else:
valid_input = True
quote = self.model.get_quote(n)
self.view.show(quote)


def main():
controller = QuoteTerminalController()
while True:
controller.run()

if __name__ == '__main__':
main()

5. 代理模式

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
# coding: utf-8


class SensitiveInfo:

def __init__(self):
self.users = ['nick', 'tom', 'ben', 'mike']

def read(self):
print('There are {} users: {}'.format(len(self.users), ' '.join(self.users)))

def add(self, user):
self.users.append(user)
print('Added user {}'.format(user))


class Info:

'''SensitiveInfo的保护代理'''

def __init__(self):
self.protected = SensitiveInfo()
self.secret = '0xdeadbeef'

def read(self):
self.protected.read()

def add(self, user):
sec = input('what is the secret? ')
self.protected.add(user) if sec == self.secret else print("That's wrong!")


def main():
info = Info()
while True:
print('1. read list |==| 2. add user |==| 3. quit')
key = input('choose option: ')
if key == '1':
info.read()
elif key == '2':
name = input('choose username: ')
info.add(name)
elif key == '3':
exit()
else:
print('unknown option: {}'.format(key))

if __name__ == '__main__':
main()

行为型

1. 责任链

多个对象来处理单个请求

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
class Event:

def __init__(self, name):
self.name = name

def __str__(self):
return self.name


class 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)
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()

2. 命令模式

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
class Invoker {  
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void action(){
this.command.execute();
}
}

abstract class Command {
public abstract void execute();
}

class ConcreteCommand extends Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
public void execute() {
this.receiver.doSomething();
}
}

class ConcreteCommand2 extends Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
public void execute() {
this.receiver.doSomething();
}
}


class Receiver {
public void doSomething(){
System.out.println("接受者-业务逻辑处理");
}
}

public class Client {
public static void main(String[] args){
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
//客户端直接执行具体命令方式(此方式与类图相符)
command.execute();

//客户端通过调用者来执行命令
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.action();
}
}

3.解释器模式

加减乘除用4个基本单位表示

4. 观察者模式

5. 状态模式

对象的行为依赖于它的某些属性值,状态的改变将导致行为的变化。

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
class State(object):

"""Base state. This is to share functionality"""

def scan(self):
"""Scan the dial to the next station"""
self.pos += 1
if self.pos == len(self.stations):
self.pos = 0
print(u"Scanning... Station is %s %s" %
(self.stations[self.pos], self.name))


class AmState(State):

def __init__(self, radio):
self.radio = radio
self.stations = ["1250", "1380", "1510"]
self.pos = 0
self.name = "AM"

def toggle_amfm(self):
print(u"Switching to FM")
self.radio.state = self.radio.fmstate


class FmState(State):

def __init__(self, radio):
self.radio = radio
self.stations = ["81.3", "89.1", "103.9"]
self.pos = 0
self.name = "FM"

def toggle_amfm(self):
print(u"Switching to AM")
self.radio.state = self.radio.amstate


class Radio(object):

"""A radio. It has a scan button, and an AM/FM toggle switch."""

def __init__(self):
"""We have an AM state and an FM state"""
self.amstate = AmState(self)
self.fmstate = FmState(self)
self.state = self.amstate

def toggle_amfm(self):
self.state.toggle_amfm()

def scan(self):
self.state.scan()


# Test our radio out
if __name__ == '__main__':
radio = Radio()
actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2
actions *= 2

for action in actions:
action()

### OUTPUT ###
# Scanning... Station is 1380 AM
# Scanning... Station is 1510 AM
# Switching to FM
# Scanning... Station is 89.1 FM
# Scanning... Station is 103.9 FM
# Scanning... Station is 81.3 FM
# Scanning... Station is 89.1 FM
# Switching to AM
# Scanning... Station is 1250 AM
# Scanning... Station is 1380 AM

6. 策略模式

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
class Strategy(object):
"""抽象算法类"""
def AlgorithmInterface(self):
raise NotImplementedError()

class ConcreteStrategyA(Strategy):
def AlgorithmInterface(self):
print '算法A'

class ConcreteStrategyB(Strategy):
def AlgorithmInterface(self):
print '算法B'

class Context(object):
"""上下文,作用就是封装策略的实现细节,用户只需要知道有哪些策略可用"""
def __init__(self, strategy):
# 初始化时传入具体的策略实例
self.strategy = strategy

def ContextInterface(self):
# 负责调用具体的策略实例的接口
self.strategy.AlgorithmInterface()

def client(cond):
# 策略模式的使用演示
# 用户只需要根据不同的条件,将具体的算法实现类传递给Context,
# 然后调用Context暴露给用户的接口就行了。
if cond == 'A':
context = Context(ConcreteStrategyA())
elif cond == 'B':
context = Context(ConcreteStrategyB())

result = context.ContextInterface()
7. 模板模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Person(object):
def Chew(self):
"""咀嚼食物"""
raise NotImplementedError()

def Swallow(self):
print '咽下去'

def Eat(self):
# 吃饭分两步,先嚼,再咽。
self.Chew()
self.Swallow()

class Man(Person):
def Chew(self):
# 男人通常狼吞虎咽
print '嚼三下'

class Woman(Person):
def Chew(self):
# 女人通常细嚼慢咽
print '嚼六下'
请作者喝一杯咖啡☕️