策略模式(Strategy Pattern)

什么是策略模式

策略模式定义了算法族, 分别封装起来, 让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户.
将内部实现委托给了行为类, 自身并不了解是如何实现的.

tips: 多用组合, 少用继承

python实现策略模式

假设我们有一个订单, 平常是原价, 但是到了节假日有多种打折方式, 我们想要用一个price_after_discount()方法解决所有打折方式.

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

def __init__(self, price, discount_strategy=None):
# 建立订单时必须设定价格, 可以选择折扣方式, 若不选择则为原价
self.price = price
self.discount_strategy = discount_strategy

def set_strategy(self, discount_strategy):
# 临时更改折扣方式
self.discount_strategy = discount_strategy

def price_after_discount(self):
# 计算价格, 若无折扣, 则按原价, 若有折扣则减去折扣
if self.discount_strategy:
discount = self.discount_strategy(self)
else:
discount = 0

# 若折扣超过原价, 则返回0
return self.price - discount if self.price > discount else 0

def __str__(self):
# 格式化tostring()方法
fmt = "<Price: {}, price after discount: {}>"
return fmt.format(self.price, self.price_after_discount())


def ten_percent_discount(order):
# 打九折, 即减去原价的10%
return order.price * 0.10


def on_sale_discount(order):
# 打75折再加20的优惠券
return order.price * 0.25 + 20


print(Order(100))
# 输出结果: <Price: 100, price after discount: 100>
print(Order(100, discount_strategy=ten_percent_discount))
# 输出结果: <Price: 100, price after discount: 90.0>
print(Order(100, discount_strategy=on_sale_discount))
# 输出结果: <Price: 100, price after discount: 55.0>

tips: 针对接口编程, 而不是针对实现编程.

观察者模式(Observer Pattern)

什么是观察者模式

观察者模式—在对象之间定义一对多的依赖, 这样一来, 当一个对象改变状态, 依赖它的对象都会收到通知并自动更新.

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
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
119
120
121
122
class Observable:
'''
Observable类追踪所有的观察者并通知他们
'''

def __init__(self):
# 初始化时创建观察者列表
self._observers = []

def register_observer(self, observer):
# 注册观察者到需要通知的观察者列表
if observer not in self._observers:
self._observers.append(observer)

def remove_observer(self, observer):
# 将观察者移除需要通知的观察者列表
try:
self._observers.remove(observer)
except ValueError:
pass

def notify_observers(self):
# 数据发生变化时通知所有观察者
for observer in self._observers:
observer.update(self)


class Data(Observable):
'''
Data类继承自Observable, 不同类型的消息可以使用同样的方法通知
'''

def __init__(self):
# 初始化时设置数据为''
Observable.__init__(self)
self._data = ''

@property
def data(self):
# get 信息
return self._data

@data.setter
def data(self, value):
# set 信息
self._data = value
# 设置信息后调用修改信息方法以通知各个观察者.
self.notify_observers()


class Observer():
'''
观察者父类
'''

def __init__(self, name=''):
# 初始化时为每个观察者单独设置一个名字
self.name = name

def update(self, Observable):
# 当消息更新时调用该方法
pass


class OrdinaryObserver(Observer):

def update(self, Observable):
# 为各类观察者重写不同的update()方法
print('Observer {} has data {}'.format(
self.name, Observable.data))


class VipObserver(Observer):

def update(self, Observable):
# 为各类观察者重写不同的update()方法
print('Distinguished observer {} has data {}'.format(
self.name, Observable.data))


# 新建两个信息类data1和data2, 并将观察者1, 2都注册到data1和data2.
data1 = Data()
data2 = Data()
observer1 = OrdinaryObserver('A')
observer2 = VipObserver('B')
data1.register_observer(observer1)
data1.register_observer(observer2)
data2.register_observer(observer1)
data2.register_observer(observer2)


data1.data = "Big news"
'''输出结果:
Observer A has data Big news
Distinguished observer B has data Big news
'''
data2.data = "Missing person notice"
'''输出结果:
Observer A has data Missing person notice
Distinguished observer B has data Missing person notice
'''
data1.data = "Latest news"
'''输出结果:
Observer A has data Latest news
Distinguished observer B has data Latest news
'''
data2.data = "Lawyer's letter"
'''输出结果:
Observer A has data Lawyer's letter
Distinguished observer B has data Lawyer's letter
'''
# data1去除观察者1, data2去除观察者2, 再对信息进行修改
data1.remove_observer(observer1)
data2.remove_observer(observer2)
data1.data = "Live news"
'''输出结果:
Distinguished observer B has data Live news
'''
data2.data = "Wanted order"
'''输出结果:
Observer A has data Wanted order
'''

装饰者模式(Decorator Pattern)

什么是装饰者模式

装饰者模式—动态地将责任附加到对象上. 想要扩展功能, 装饰着提供有别于继承的另一种选择.

tips: 类应该对扩展开放, 对修改关闭

python实现装饰者模式

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

import time


def time_it(func):
# 创建一个时间装饰器, 用于计算函数运行的时间.

def call_func():
start_time = time.time()
func()
stop_time = time.time()
print("运行时间是{}".format(stop_time-start_time))

return call_func


# 用@方法的方式使用装饰器
@time_it
def test():
print("----test----")
for i in range(1000):
pass


test()
# 输出结果为: 运行时间是0.0322401523590087

也可以按照自己的需求编写装饰器:

比如在店里买饮料, 需要选择是否添加牛奶, 摩卡等, 这时就可以使用装饰者模式.

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
class Beverage():
'''
饮料父类
'''

def __init__(self):
self._description = "Unknown beverage"
self._cost = 0

def get_description(self):
# 获取饮料的描述
return self._description

def get_cost(self):
# 获取饮料的价格
return self._cost


class Condiment(Beverage):
'''
调料父类, 继承自Beverage并不是为了继承行为, 而是为了类型匹配
'''

def get_description():
pass

def get_cost():
pass


class DarkRoast(Beverage):
# 深焙咖啡类, 并初始化描述和价格
def __init__(self):
self._description = "DarkRoast"
self._cost = 12.5


class Espresso(Beverage):
# 浓缩咖啡类, 并初始化描述和价格
def __init__(self):
self._description = "Espresso"
self._cost = 13.8


class Mocha(Condiment):
# 配料摩卡, 并初始化描述和价格
def __init__(self, beverage):
self.beverage = beverage
self._cost = 2.5

def get_description(self):
return self.beverage.get_description() + ", Mocha"

def get_cost(self):
return round(self.beverage.get_cost() + self._cost, 2)


class Whip(Condiment):
# 配料奶泡, 并初始化描述和价格
def __init__(self, beverage):
self.beverage = beverage
self._cost = 1.4

def get_description(self):
return self.beverage.get_description() + ", whip"

def get_cost(self):
return round(self.beverage.get_cost() + self._cost, 2)


# 新建一个深焙咖啡, 并添加摩卡和奶泡
beverage1 = DarkRoast()
beverage1 = Mocha(beverage1)
beverage1 = Whip(beverage1)

# 新建一个浓缩咖啡, 并添加两次奶泡
beverage2 = Espresso()
beverage2 = Whip(beverage2)
beverage2 = Whip(beverage2)

print(beverage1.get_description(), " ¥", beverage1.get_cost())
# 输出结果: DarkRoast, Mocha, whip ¥ 16.4
print(beverage2.get_description(), " ¥", beverage2.get_cost())
# 输出结果: Espresso, whip, whip ¥ 16.6

工厂模式(Factory Pattern) 和 抽象工厂模式(Abstract Factory Pattern)

什么是工厂模式和抽象工厂模式

工厂模式—定义了一个创建对象的接口, 但由子类决定要实例化的类是哪一个. 工厂方法让类把实例化推迟到子类.
抽象工厂模式—提供一个接口, 用于创建相关或依赖对象的家族, 而不需要明确指定具体类.

tips: 要依赖抽象类而不依赖具体类

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
class ChineseLocalizer:
'''简单为几个单词中文本地化'''

def __init__(self):
self.translations = {"dog": "狗", "cat": "猫"}

def localize(self, msg):
'''如果没有该单词的翻译则返回原词'''
return self.translations.get(msg, msg)


class EnglishLocalizer:
'''简单重复该单词'''

def localize(self, msg):
return msg


def get_localizer(language="English"):
'''语言工厂'''
localizers = {
"English": EnglishLocalizer,
"Chinese": ChineseLocalizer,
}

return localizers[language]()


# 使用工厂模式创建本地化类
eng = get_localizer(language="English")
ch = get_localizer(language="Chinese")

print(eng.localize('dog'), ch.localize('dog'))
# 输出结果: dog 狗
print(eng.localize('cat'), ch.localize('cat'))
# 输出结果: cat 猫
print(eng.localize('pig'), ch.localize('pig'))
# 输出结果: pig pig

python实现抽象工厂模式

在Java和其他语言中, 抽象工厂模式用于提供用于创建相关或依赖对象的接口, 而无需指定它们的实际类. 其思想是根据业务逻辑, 平台选择等决定抽象对象的创建.
在Python中, 我们使用的接口只是一个Callable对象, 这是Python中的”内置”接口, 在正常情况下, 我们可以简单地将类本身用作该Callable对象, 因为类在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
import random


class PetShop:
'''一个宠物商店'''

def __init__(self, animal_factory=None):
#宠物工厂只是一个抽象工厂, 我们可以在未来使其实例化
self.pet_factory = animal_factory

def show_pet(self):
# 使用抽象工厂创建和展示宠物
pet = self.pet_factory()
print("We have a lovely {}, it says {}.".format(pet, pet.speak()))


class Dog:
# Dog工厂
def speak(self):
return "woof"

def __str__(self):
return "Dog"


class Cat:
# Cat工厂
def speak(self):
return "meow"

def __str__(self):
return "Cat"


# 额外的工厂:
def random_animal():
# 创建一个随机动物
return random.choice([Dog, Cat])()


# 创建一个猫店
cat_shop = PetShop(Cat)
cat_shop.show_pet()
# 输出结果: We have a lovely Cat, it says meow.

# 售卖随机动物的商店
shop = PetShop(random_animal)
for i in range(3):
shop.show_pet()
'''输出结果:
We have a lovely Dog, it says woof.
We have a lovely Dog, it says woof.
We have a lovely Cat, it says meow.
'''

单例模式(Singleton Pattern)

什么是单例模式

单例模式—确保一个类只有一个实例, 并提供一个全局访问点.

python实现单例模式

python实现单例模式大体上有四种方法:

  • 函数装饰器实现单例模式
  • 类装饰器实现单例模式
  • new关键字实现单例模式
  • metaclass实现单例模式

装饰器实现单例模式

使用python自带的装饰器可以简单实现装饰器模式.

函数装饰器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def singleton(cls):
# 函数装饰器实现单例模式
_instance = {}

def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner


@singleton
class Test():
def __init__(self):
pass


test1 = Test()
test2 = Test()
# 测试两个类实例指针是否一样
print(id(test1) == id(test2))
# 输出结果: True

类装饰器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Singleton():
# 类装饰器实现单例模式
def __init__(self, cls):
self._cls = cls
self._instance = {}

def __call__(self):
# 类被调用时会触发此方法
if self._cls not in self._instance:
self._instance[self._cls] = self._cls()
return self._instance[self._cls]


@Singleton
class Test():
def __init__(self):
pass


test1 = Test()
test2 = Test()
print(id(test1) == id(test2))
# 输出结果: True

使用new关键字实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Singleton():
# new关键字实现单例模式
_instance = None

def __new__(cls, *args, **kw):
# 在新建类实例时调用该方法
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kw)
return cls._instance

def __init__(self):
pass


singleton1 = Singleton()
singleton2 = Singleton()
print(id(singleton1) == id(singleton2))
# 输出结果: True

使用metaclass实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Singleton(type):
# metaclass实现单例模式
_instances = {}

def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(
Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]


class Test(metaclass=Singleton):
pass


test1 = Test()
test2 = Test()
print(id(test1) == id(test2))

这里, 我们将 metaclass 指向 Singleton 类, 让 Singleton 中的 type 来创造新的实例.

命令模式(Command Pattern)

什么是命令模式

命令模式—将请求封装成对象, 这可以让你使用不同的请求, 队列, 或者日志请求来参数化其他对象. 命令模式也可以支持撤销对象.

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
76
77
class RemoteControl():
'''
遥控器类, 用于注册命令和触发命令.
'''

def __init__(self):
self.buttons = {}
self.records = []

def set_command(self, button, command):
# 注册命令到遥控器按键上
self.buttons[button] = command

def button_on_click(self, button):
# 当按键被触发时执行命令, 并记录该命令
self.buttons[button].execute()
self.records.append(button)

def undo_on_click(self):
# 当用户点击撤销时按顺序撤销命令
if len(self.records) > 0:
button = self.records.pop()
self.buttons[button].undo()


class Command():
# 命令父类
def execute(self):
pass

def undo(self):
pass


class LightOnCommand(Command):
# 开灯命令
def execute(self):
# 执行
print("Light on!")

def undo(self):
# 撤销
print("Light off!")


class LightOffCommand(Command):
# 关灯命令
def execute(self):
# 执行
print("Light off!")

def undo(self):
# 撤销
print("Light on!")


# 新建遥控器类和命令类
remote_control = RemoteControl()
light_on_command = LightOnCommand()
light_off_command = LightOffCommand()
# 将命令类注册到遥控器按键上
remote_control.set_command(0, light_on_command)
remote_control.set_command(1, light_off_command)
# 点击按键
remote_control.button_on_click(1)
remote_control.button_on_click(0)
''' 输出结果:
Light off!
Light on!
'''
# 点击撤销按键
remote_control.undo_on_click()
remote_control.undo_on_click()
'''输出结果:
Light off!
Light on!
'''

适配器模式(Adapter Pattern)

什么是适配器模式

适配器模式—将一个类的接口转换成客户期望的另一个接口, 适配器让原本不兼容的类可以合作无间.

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
class Human():
# 人类类, 会speak()
def speak(self):
print("Hello")


class Dog():
# 狗狗类, 会bark()
def bark(self):
print("woof")


class AdapterHuman(Human):
# 让狗狗套进人皮套, 学会speak()
def __init__(self, dog):
self.dog = dog

def speak(self):
self.dog.bark()


dog = Dog()
human = Human()
dogman = AdapterHuman(dog)

dogman.speak()
human.speak()
'''输出结果:
woof
Hello
'''

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
class Dog:
def __init__(self):
self.name = "Dog"

def bark(self):
return "woof!"


class Adapter():
"""通过替代方法来适配对象.
Usage
------
dog = Dog()
dog = Adapter(dog, make_noise=dog.bark)
"""

def __init__(self, obj, **adapted_methods):
"""我们在dict中设置适配方法."""
self.obj = obj
self.__dict__.update(adapted_methods)

def __getattr__(self, attr):
"""所有未适配的调用也都传递给对象."""
return getattr(self.obj, attr)

def original_dict(self):
"""返回原始对象的dict"""
return self.obj.__dict__


dog = Dog()
dog_adapter = Adapter(dog, make_noise=dog.bark)

print(dog.name)
print(dog_adapter.name)
print(dog.bark())
print(dog_adapter.make_noise())
print(dog_adapter.bark())
'''输出结果:
Dog
Dog
woof!
woof!
woof!
'''

外观模式(Facade Pattern)

什么是外观模式

外观模式—提供了一个统一的接口, 用来访问子系统中的一群接口. 外观定义了一个高层接口, 让子系统更容易使用.

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
# 一个复杂的电脑运行
class CPU:
"""
简单的CPU类.
"""

def freeze(self):
print("Freezing processor.")

def jump(self, position):
print("Jumping to:", position)

def execute(self):
print("Executing.")


class Memory:
"""
简单的储存器类.
"""

def load(self, position, data):
print("Loading from {0} data: '{1}'.".format(position, data))


class SolidStateDrive:
"""
简单的SSD类.
"""

def read(self, lba, size):
return "Some data from sector {0} with size {1}".format(lba, size)


class ComputerFacade:
"""
用外观模式让计算机运行变得简单起来.
"""

def __init__(self):
self.cpu = CPU()
self.memory = Memory()
self.ssd = SolidStateDrive()

def start(self):
self.cpu.freeze()
self.memory.load("0x00", self.ssd.read("100", "1024"))
self.cpu.jump("0x00")
self.cpu.execute()


computer_facade = ComputerFacade()
computer_facade.start()
'''输出结果
Freezing processor.
Loading from 0x00 data: 'Some data from sector 100 with size 1024'.
Jumping to: 0x00
Executing.
'''

模板模式(Template Pattern)

什么是模板模式

模板模式—在一个方法中定义一个算法的骨架, 而将一些步骤延迟到子类中. 模板方法使得子类可以在不改变算法结构的情况下, 重新定义算法中的某些步骤.

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
"""三种不同的获取数据方式"""


def get_text():
return "plain-text"


def get_pdf():
return "pdf"


def get_csv():
return "csv"


# 转换数据格式
def convert_to_text(data):
print("[CONVERT]")
return "{} as text".format(data)


# 保存数据
def saver():
print("[SAVE]")


def template_function(getter, converter=False, to_save=False):
"""模板方法, 根据自己的需要使用不同的方法, 基础的算法骨架是一样的"""
data = getter()
print("Got `{}`".format(data))

if len(data) <= 3 and converter:
data = converter(data)
else:
print("Skip conversion")

if to_save:
saver()

print("`{}` was processed".format(data))


template_function(get_text, to_save=True)
"""输出结果:
Got `plain-text`
Skip conversion
[SAVE]
`plain-text` was processed
"""
template_function(get_pdf, converter=convert_to_text)
"""输出结果:
Got `pdf`
[CONVERT]
`pdf as text` was processed
"""
template_function(get_csv, to_save=True)
"""输出结果:
Got `csv`
Skip conversion
[SAVE]
`csv` was processed
"""

迭代器模式(Iterator Pattern)

什么是迭代器模式

迭代器模式—提供一种方法顺序访问一个聚合对象中的各个元素, 而又不暴露其内部的表示.

python实现迭代器模式

python可以通过 yield 或者 iter()方法 快速简单实现迭代器模式.

利用yield迭代方法快速跳出二重循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
listA = [5, 3, 1, 7, 2]
listB = [2, 8, 3, 6, 9]


def get_pairs(listA, listB):
"""在listA和listB范围中生成索引对"""
for i in listA:
for j in listB:
yield i, j


for i, j in get_index(listA, listB):
if i == j:
break

利用iter()方法进行迭代:

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
class NumberWords:
"""数数, 从start到stop的英文数字迭代"""

_WORD_MAP = (
'one',
'two',
'three',
'four',
'five',
)

def __init__(self, start, stop):
self.start = start
self.stop = stop

def __iter__(self):
# 该方法使得这个类可以迭代
return self

def __next__(self):
# 该方法使得这个类成为迭代器, 每次迭代会调用该方法
if self.start > self.stop or self.start > len(self._WORD_MAP):
raise StopIteration
current = self.start
self.start += 1
return self._WORD_MAP[current - 1]


for number in NumberWords(start=1, stop=5):
print(number)
"""输出结果:
one
two
three
four
five
"""

组合模式(Composite Pattern)

什么是组合模式

组合模式—允许你将对象组合成树状结构来表现”整体/部分”层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合.

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
class Graphic():
"""绘图父类 """

def render(self):
raise NotImplementedError("You should implement this!")


class CompositeGraphic(Graphic):
# 绘制复杂图像

def __init__(self):
self.graphics = []

def render(self):
for graphic in self.graphics:
graphic.render()

def add(self, graphic):
self.graphics.append(graphic)

def remove(self, graphic):
self.graphics.remove(graphic)


class Ellipse(Graphic):
# 绘制椭圆图像

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

def render(self):
print("Ellipse: {}".format(self.name))


# 三个椭圆
ellipse1 = Ellipse("1")
ellipse2 = Ellipse("2")
ellipse3 = Ellipse("3")
# 两个复杂图像
graphic1 = CompositeGraphic()
graphic2 = CompositeGraphic()
# 将三个椭圆添加到这两个复杂图像中
graphic1.add(ellipse1)
graphic1.add(ellipse2)
graphic2.add(ellipse3)
# 再将这两个复杂图像再添加到新的复杂图像中
graphic = CompositeGraphic()
graphic.add(graphic1)
graphic.add(graphic2)
# 所有图像都可以任意组合, 输出只需要使用render()方法即可
graphic.render()
"""输出结果:
Ellipse: 1
Ellipse: 2
Ellipse: 3
"""

状态模式(State Pattern)

什么是状态模式

状态模式—允许对象在内部状态改变时改变它的行为, 对象看起来好像修改了它的类.

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
76
77
class State:
"""状态父类"""

def scan(self):
"""调频"""
self.pos += 1
if self.pos == len(self.stations):
self.pos = 0
print("Scanning... Station is {} {}".format(
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("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("Switching to AM")
self.radio.state = self.radio.amstate


class Radio:

"""一个收音机. 有一个调频按钮和AM/FM切换按钮."""

def __init__(self):
"""可以收听中波和短波, 初始化为中波"""
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()


# 新建一个收音机, 并进行调频和切换波段
radio = Radio()
actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2
actions *= 2
for action in actions:
action()
'''输出结果
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
'''

代理模式(Proxy Pattern)

什么是代理模式

代理模式—为一个对象提供一个替身或占位符以访问这个对象.

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
class Subject:
"""
RealSubject和Proxy的接口应该是相同的,
因为客户端应该能够使用RealSubject或Proxy, 而不需要更改代码.
并非所有时候都需要此接口. 关键是客户端应该能够互换使用RealSubject或Proxy,
而无需更改代码.
"""

def do_the_job(self, user):
raise NotImplementedError()


class RealSubject(Subject):
"""这是真正工作的对象."""

def do_the_job(self, user):
print("I am doing the job for {}".format(user))


class Proxy(Subject):
"""这个是代理对象"""

def __init__(self):
self._real_subject = RealSubject()

def do_the_job(self, user):
"""
记录和控制访问.
"""

print("[log] Doing the job for {} is requested.".format(user))

if user == "admin":
self._real_subject.do_the_job(user)
else:
print("[log] I can do the job just for `admins`.")


def client(job_doer, user):
job_doer.do_the_job(user)


proxy = Proxy()
real_subject = RealSubject()
client(proxy, 'admin')
''' 输出结果:
[log] Doing the job for admin is requested.
I am doing the job for admin
'''
client(proxy, 'anonymous')
'''输出结果:
[log] Doing the job for anonymous is requested.
[log] I can do the job just for `admins`.
'''
client(real_subject, 'admin')
'''输出结果:
I am doing the job for admin
'''
client(real_subject, 'anonymous')
'''输出结果:
I am doing the job for anonymous
'''

后记

以上例子大部分是来自于github上的项目 python-patterns, 还有很多有趣的设计模式没有在这篇文章中记录, 有兴趣的可以去github上查阅, 这些设计模式也经常混搭使用, 但是要记住并不是大部分情况都要使用设计模式, 切忌生搬硬套.

参考文献

[1] Freeman E, Robson E, Bates B, et al. Head first design patterns[M]. “ O’Reilly Media, Inc.”, 2008.
[2] python-patterns