结构梳理>>>
第一部分: 创建型模式
- 工厂模式
- 工厂方法
- 抽象工厂
- 建造者模式
- 原型模式
- 单例模式
第二部分: 结构型模式
- 适配器模式
- 修饰器模式
- 外观模式
- 享元模式
- 模型-视图-控制器模式
- 代理模式
第三部分: 行为型模式
- 责任链模式
- 命令模式
- 解释模式
- 观察者模式
- 状态模式
- 策略模式
- 模板模式
干货>>>
何为设计模式?
==>大牛们踩过了无数的坑总结出来的软件设计中的推荐方案
第一部分: 创建型模式
跟对象创建有关的一系列模式
- 工厂模式
客户端请求对象时无需知道对象的来源,直接通过向函数和类向工厂传递参数创建对象,简化对象的创建过程
工厂方法
何为工厂?
==>加工类的地方
何为工厂方法?
==>以方法(函数)作为工厂
实现:
定义函数,根据条件返回不同类的实例
1) 定义多个类(平行的类)
2) 定义工厂方法-函数,通过不同输入参数的条件判断将上面定义的类分别赋值同一个变量,最后返回变量的调用-类的实例对象
3) 可以再定义一系列函数调用工厂方法进行封装,实现不同功能(异常处理,写日志等)
抽象工厂
何为抽象工厂?
==>一组工厂方法,每个工厂方法返回不同实例对象
为什么要用抽象工厂?
==>优点:工厂方法的泛化,使对象创建更容易追踪;将对象创建和使用解耦;优化内存占用和性能潜力;可通过改变激活工厂方法动态改变应用行为,不用终止重启,改变用户使用应用的观感(看不懂?往下看)
什么时候用?
==>创建了很多工厂方法,难以维护了,此时,我们需要把创建实例对象的过程合并在一起
实现:
1) 定义多个类(平行的类)
2) 定义抽象工厂-类,通过定义类的不同方法(make_a、make_b...),返回上面定义类的实例对象(有参数的在__init__中定义)==>将抽象工厂作为一个接口,实现动态激活make_a、make_b等工厂方法
3) 可以再定义一系列类,对抽象工厂进行封装。
例如:再定义一个类Env,__init__中传入抽象工厂的调用-类的实例对象,通过调用实例的make_a、make_b方法,实现在Env中初始化类;定义其他方法,实现不同功能
- 建造者模式
用于细粒度控制复杂对象的创建过程
何为建造者模式?
==>创建一个由多个部分构成的对象,每个构成需要一步步完成,就像盖房子,每个部分都建造好,对象才算最终创建
什么时候用?
1) 页面生成器
2) 文档转换器
3) 用户界面
4) 表单创建工具
再回首:
工厂模式:单步创建对象;调用立即返回实例对象;
建造者模式:多步创建对象;需要时才返回最终实例对象;
实现:
引入建造者、指挥者、
1) 定义一个类A(要创建的类,创建时需要一步步调用类中不同的属性和方法)
2) 定义不同类的Builder(建造者),实例化时传入A的实例;定义多个函数-代表创建过程的多个步骤(通过调用实例的属性和方法实现),实现不同建造者的不同创建步骤
3) 定义一个类Constructer(指挥者),定义方法,传入建造者作为参数,按照指定的顺序执行建造者定义的一系列方法(建造步骤)
- 原型模式
创建对象的克隆-副本(注意引用和副本的区别);copy.deepcopy的使用
实现:
通过定义类,定义方法,调用copy.deepcopy(obj)实现对象克隆
- 单例模式
每次初始化类时生成同一个实例对象
实现:
# 1. new方法实现 class Singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(*args, **kwargs)
return cls._instance
class MyClass:
a = 1
# 2. 装饰器实现
from functools import wraps def singleton(cls):
_instance = {} @wraps(cls)
def check_instance(*args, **kwargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]
return check_instance @singleton
class MyClass:
a = 1 # 3. metaclass实现
class Singleton(type):
_instance = {} def __call__(cls, *args, **kwargs):
if cls not in cls._instance:
cls._instance[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instance[cls] class MyClass(metaclass=Singleton):
# __metaclass__ = Singleton
a = 1
第二部分: 结构型模式
处理系统中不同实体(类、对象)间关系,通过对象组合方式,创造新功能
- 适配器模式
实现不兼容接口间兼容
遵循开放封闭原则(扩展开放、修改封闭)
什么时候用?
不修改原始代码的情况下,将老组件用于新系统or新组件用于老系统;组件以外部库提供,无法访问代码
实现
方式1:继承
方式2:类的内部字典(更地道)
1) 定义类(待访问的代码类)
2) 定义类(可访问的代码)
3) 定义类Adapter,初始化对象时传入待访问的类对象、待访问的类的方法(dict形式),将待访问的类的方法update到self.__dict__中
*****external.py*****
class Synthesizer:
def __init__(self, name):
self.name = name
def __str__(self):
return 'the {} synthesizer'.format(self.name)
def play(self):
return 'is playing an electronic song' class Human:
def __init__(self, name):
self.name = name
def __str__(self):
return '{} the human'.format(self.name)
def speak(self):
return 'says hello'
*****adapter.py*****
from external import Synthesizer, Human
class Computer:
def __init__(self, name):
self.name = name
def __str__(self):
return 'the {} computer'.format(self.name)
def execute(self):
return 'executes a program' 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)))
for i in objects:
print('{} {}'.format(str(i), i.execute()))
if __name__ == "__main__":
main()
- 修饰器模式
无序使用子类,动态扩展对象的行为(能用组合,不用继承)-将功能添加到对象
什么时候用?
实现横切关注点
1) 数据校验
2) 事务处理(这里的事务类似于数据库事务,意味着要么所有步骤都成功完成,要么事务失败)
3) 缓存
4) 日志
5) 监控
6) 调试
7) 业务规则
8) 压缩
9) 加密
图形用户界面(GUI)工具集
实现:
python修饰器实现修饰器模式
- 外观模式
一种简化复杂系统访问的方式
为什么要用外观模式?
隐藏系统的内部复杂性,通过一个简化的接口向客户端暴露必要的部分(在复杂系统做了一个抽象层)
- 享元模式
复用对象,提高系统的资源利用率
- 模型-视图-控制器模式
- 代理模式
第三部分: 行为型模式
- 责任链模式
- 命令模式
- 解释模式
- 观察者模式
- 状态模式
- 策略模式
- 模板模式