一、 创建型的设计模式
1、 工厂模式(Factory):解决对象创建问题
2、 构造模式(Builder): 控制解决复杂对象的创建问题
3、 原型模式(Prototype): 通过原型的克隆去创建新的实例
4、 单例模式(Brog/Singleton): 一个类只能创建同一个对象
5、 对象池模式(Pool): 预先分配同一个类型的一组实例
6、 惰性计算模式(Lazy Evaluation): 延迟计算(Python的property)
解决对象创建的问题, 解耦对象的创建和使用, 包括工厂方法和抽象工厂
# 工厂方法的一个例子
klass_dict = {}
def register(type):
def deco(cls):
if cls not in klass_dict.values():
klass_dict[type] = cls
return deco
@register('Dog')
class Dog:
def speak(self):
print("WangWang!")
@register('Cat')
class Cat:
def speak(self):
print("MiaoMiao!")
def animal(speak_type):
klass = klass_dict.get('speak_type')
return klass
核心: 将一个过程需要自定义的部分进行细化分类即可。
用来控制复杂对象的构造, 创建。 比如买电脑, 工厂模式直接给你电脑, 而构造模式可以允许你自定义你的电脑的配置, 组装后返回给你。
import attr
@attr.s
class Computer(obj):
# 电脑类, 只有个机箱序列号, 其他None
serial_num = attr.ib()
memory = attr.ib(default=None)
hdd = attr.ib(default=None)
gpu = attr.ib(default=None)
def __repr__(self):
info = ("内存: {}GB:".format(self.memory),
"硬盘:{}GB".format(self.hdd),
"显卡: {}".format(self.gpu))
return '\n'.join(info)
@attr.s
class ComputerBuilder(obj):
# 装机人员类, 接收一个机箱壳子
computer = attr.ib(default=Computer())
def configure_memory(self. amount):
self.computer.memory = amount
def configure_hdd(self, amonut):
self.computer.hdd = amout
def configure_gpu(self, gpu_model):
self.computer.gpu = gpu_model
@attr.s
class HardwareEngineer(obj):
builder = attr.ib(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
# 创建一个造机工厂
engineer = HardwarEngineer()
engineer.construct_computer(hdd=1024, memory=32, gpu='GeForce GTX TITAN Plus'
my_computer = enginner.computer
print my_computer
通过克隆原型来创建新的实例, 可以使用相同的原型, 通过修改部分属性来创建心得实例。
用途: 对于一些创建实例开销比较高的地方可以使用原型模式, 也叫Copy忍者卡卡西模式。
一个类创建出来的对象是同一个, 例如:Python模块就是单例的, 无论导入调用多少次都是同一个对象。
class Singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
class B(Singleton):
pass
b = B()
c = B()
id(b) == id(c) # True
二、结构型设计模式
1、 装饰器模式(Decorater): 无需子类化扩展对象功能
2、 代理模式(Proxy): 把一个对象的操作代理到另一个对象
3、 适配器模式(Adapter): 通过一个间接层适配统一接口
4、 外观模式(Facade): 简化复杂对象的访问问题
5、 享元模式(Flyweight): 通过对象复用改善资源利用, 比如连接池
6、 Model-View-Controller(MVC):解耦合显示逻辑和业务逻辑, 比如Django, Flask, Tornado等框架都适合这种模式。
把对象的操作代理到另一个对象, 这里可以用到Stack、Queue, 把操作代理到deque。
from collections import deque
class Stack(obj):
def __init__(self):
self._deque = deque()
def push(self, value):
return self._deque.append(value)
def pop(self):
return self._deque.pop()
def empty(self):
return len(self._deque) == 0
把不同的对象的接口适配到同一个接口, 当需要不同的对象统一接口的时候可以使用适配器模式
class Dog(obj):
def __init__(self):
self.name = 'dog'
def bark(self):
return 'wangwang'
class Cat(obj):
def __init__(self):
self.name = 'cat'
def miao(self);
return 'miaomiao'
class Adapter:
def __init__(self, obj, **adapter_methods):
self.obj = obj
self.__dict__.update(adapted_methods)
def __getattr__(self, attr):
return getattr(self.obj, attr)
objects = []
dog = Dog()
objects.append(Adapter(dog, make_noise=dog.bark))
cat = Cat()
objects.append(Adapter(cat, make_noise=cat.miao))
for obj in objects:
print "name:{}, ac:{}".format(obj.name, obj.make_noise())
三、行为型模式
1、 迭代器模式(Iterator): 通过统一identify接口迭代对象
2、 观察者模式(Observer)—发布订阅: 对象发生变化的时候, 观察者执行相应的动作
3、 策略模式(Strategy): 针对不同的输入使用不容的策略
Python内置对迭代器模式的支持, 可以用for遍历各种Iterable的数据类型, 不可迭代对象需要用(next__和__iter) 实现迭代器, 可以迭代的对象只使用__iter__
from collections import deque
class Stack(obj):
def __init(self):
self._deque =deque()
def push(self, value):
return self._deque.append(value)
def pop(self):
return self._deque.pop()
def empty(self):
return len(self._deque) == 0
def __iter__(self):
res = []
for i in self._deque:
res.append(i)
for i in reversed(res):
yield i
发布订阅最为常见, 发布订阅用于解耦合逻辑, 可以通过回调等方式去实现, 当条件发生的时候可以使用相应的回调函数去触发下一层设计的逻辑
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:
print('Failed to remove : {}'.format(observer))
def notify(self):
[o.notify_by(self) for o in self.observers]
class Formatter(Publisher):
def __init__(self, name):
super().__init__()
self.name = name
self._data = 0
@property
def data(self):
return self._data
@data.setter
def data(self, new_value):
self._data = int(new_value)
self.notify()
class BinaryFormatter:
def notify_by(self, publisher):
print("{} : {} has now bin data = {}".format(
type(self).__name__,
publisher.name,
bin(publisher.data)))
根据不同输入采用不容的策略, 对歪暴露统一的接口, 内部采用不同的策略进行计算返回结果(这种和rpc或者云函数的意思蛮接近的, 外部只管按规则调用, 我直接返回结果给你, 其中过程外部是不需要知道的)
class Order:
def __init__(self, price, discount_strategy=None):
self.price = price
self.discount_strategy = discount_strategy
def price_after_discount(self):
if self.discount_strategy:
discount = self.discount_strategy(self)
else:
discount = 0
return self.price - discount
def __repr__(self):
fmt='<Price: {}, price after discount: {}>'
return fmt.fotmat(self.price, self.price_after_discount())