python-patterns

曹疏珂
2023-12-01

behavioral行为

catalog (目录模式)

类中根据init指定的参数执行相应相应的函数
使用一个字典来代替多个条件。
调用方式
被调用函数:静态方法无参数

self._static_method_choices[self.param]()

被调用函数:普通函数

self._instance_method_choices[self.param].__get__(self)()

被调用函数:类函数

self._class_method_choices[self.param].__get__(None, self.__class__)()
def __get__(self, obj: Optional[object], type: Optional[type]) -> MethodType: ...

Chain of responsibility(责任链)

对象版的:if … elif … elif … else …
扩充:tree of responsibility
实现
抽象类:Handler

def handle(self, request):
	res = self.check_range(request) # 划分范围,及处理
	if not res and self.successor: # 责任传递
		self.successor.handle(request)
def check_range(self, request):pass

command(命令模式)

封装执行一个动作或者触发一个时间的所有信息
例子:
MoveFileCommand
变量src、dest
函数 execute、undo、rename
iterator(迭代器)
遍历容器并获取元素
Mediator(中介者)
系统中的对象通过一个中介交流而不是直接交流。减少对象依赖,因此减少耦合。
例子:用户通过聊天室聊天。

memento (备忘录)

保存一个对象之前的状态
实例
定义用函数,返回函数名(闭包)
定义用类,可用作装饰器。初始化保留函数,__get__方法返回闭包,state状态就保留着,失败直接恢复。

observer(观察者)

维护依赖列表项,并在状态改变时唤醒他们。
基类——观察者管理列
value 观察列表
方法:attach:添加观察者;detach:减少观察者;notify:唤醒观察者
数据类:继承基类
观察者类,处理观察值。

publish_subscribe(发布订阅模式)

消息订阅与发布。类似订报纸。
实例
Provider 消息订阅、取消、新增消息以及分发功能
Publisher 发布消息,保留一个provider实例
Subscriber 订阅消息

registry (注册模式)

记录一个类的所有子类
把生成的实例记录到字典中,通过键值(如类名可找到相应的实例)

specification(规约模式)

通过boolean逻辑来串联重组已有规则
规约模式经常在DDD中使用,用来将业务规则(通常是隐式业务规则)封装成独立的逻辑单元,从而将隐式业务规则提炼为显示概念,并达到代码复用的目的。
实现

Specification类:
def and_specification(self, candidate):raise NotImplementedError()
def or_specification(self, candidate):raise NotImplementedError()
def not_specification(self):raise NotImplementedError()
抽象方法def is_satisfied_by(self, candidate): pass
CompositeSpecification(Specification)类,实现and,or,not方法

实例

root_specification = UserSpecification().and_specification(SuperUserSpecification())

state(状态模式)

定义: 状态模式允许对象在内部状态改变时改变他的行为,对象看起来好像修改了他的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
何时使用:代码中包含大量与对象状态有关的条件语句。
注:可用有限状态机DFA实现。

strategy(策略模式)

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
例子:订单打折,有多种订单打折策略。传入不同函数,如10%打折,促销打折。

template(模板模式)

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
何时使用:有一些通用的方法。

visitor(访问者模式)

意图:主要将数据结构与数据操作分离。
主要解决:稳定的数据结构和易变的操作耦合问题。
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。
如何解决:在被访问的类里面加一个对外提供接待访问者的接口。
使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

creational创建

abstract_factory抽象工厂模式

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
value:类
borg(MonoState) 单一状态模式
单例的一种实现方式
共享状态
实例:数据库连接管理
实现:self.dict = self.__shared_state # __shared_state = {} 为类变量

builder建造者模式

意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。

factory工厂模式

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。

lazy_evaluation懒执行模式

延迟表达式计算直到值需要时,并且避免重复计算
实现:封装方法,作为装饰器。

object_pool对象池模式

意图:在创建对象比较昂贵,或者对于特定类型能够创建的对象数目有限制时,管理对象的重用。
例子
queue.Queue
prototype原型模式
意图:减少应用程序所需的类的数量
主要解决:在运行期建立和删除原型。
何时使用

  1. 当一个系统应该独立于它的产品创建,构成和表示时。
  2. 当要实例化的类是在运行时刻指定时,例如,通过动态装载。
  3. 为了避免创建一个与产品类层次平行的工厂类层次时。
  4. 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

使用场景

  1. 资源优化场景。
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  3. 性能和安全要求的场景。
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  5. 一个对象多个修改者的场景。
  6. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  7. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。
    fundamental基础

delegation_pattern委托

使对象复合获得和继承相同的代码重用
在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。

structural结构

3-tier 三层架构:界面层、业务逻辑层、数据访问层

adapter适配器模式

将不同的接口整合到一个特定的API而不需要修改原来的对象。

bridge桥接模式

目的:将抽象部分与它的实现部分分离,使他们都可以独立地变化。
“将抽象部分与它的实现部分分离”指实现系统可能有多个角度分类,每一种分类都可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
好处

  1. 分离接口及实现部分:接口与实现分离有助于分层,产生更好的结构化系统,系统的高层次部分仅需要关注抽象接口即可。
  2. 提高可扩展性:在一个维度有变化,不需要调整另外一个维度的任何代码;可以独立地对多个维度进行扩展。
  3. 实现细节对客户透明:客户不需要关注任何实现细节,仅仅需要关注抽象类逻辑。

composite组合模式

主要功能:将对象组合成树形结构以表示“部分-整体”的层次结构。这可以使得用户在使用单个对象和组合对象时有一致性。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用:

  1. 您想表示对象的部分-整体层次结构(树形结构)。
  2. 您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
    UML类图
    File, Directory 继承Entry,Entry聚合于Directory(has-a关系)

UML类图参考 https://www.cnblogs.com/zyrblog/p/9237943.html

decorate装饰模式

用处:动态添加新功能而不改变原有实现。不像继承,新功能添加到所有子类,而是只添加到特定的一个对象。
实例:为字符串添加xml格式的tag

facade外观模式

目的:通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。
好处:该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
例子:台式机开机只需要按一个开机按钮。

flyweight享元模式

意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
适用性

  1. 一个应用程序使用了大量的对象。
  2. 完全由于使用大量的对象,造成很大的存储开销。
  3. 对象的大多数状态都可变为外部状态。
  4. 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
    应用程序不依赖于对象标识。
    弱引用:弱引用指引用一个对象但不增加它的引用计数器 https://blog.51cto.com/sleepd/1073044

frontcontroller前段控制器模式

用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。
实现
前端控制器(Front Controller) - 处理应用程序所有类型请求的单个处理程序,应用程序可以是基于 web 的应用程序,也可以是基于桌面的应用程序。
调度器(Dispatcher) - 前端控制器可能使用一个调度器对象来调度请求到相应的具体处理程序。
视图(View) - 视图是为请求而创建的对象。
MVC模型-视图-控制器模式
用于应用程序的分层开发

proxy代理模式

意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制。
例子:客户——代理沟通——经理

dependency_injection依赖注入

实现控制反转
如果一个类A 的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题,类A也需要进行改造,如果这样的情况较多,每个类之间都有很多依赖,那么就会出现牵一发而动全身的情况,程序会极难维护,并且很容易出现问题。要解决这个问题,就要把A类对B类的控制权抽离出来,交给一个第三方去做,把控制权反转给第三方,就称作控制反转(IOC Inversion Of Control)。控制反转是一种思想,是能够解决问题的一种可能的结果,而依赖注入(Dependency Injection)就是其最典型的实现方法。由第三方(我们称作IOC容器)来控制依赖,把他通过构造函数、属性或者工厂模式等方法,注入到类A内,这样就极大程度的对类A和类B进行了解耦。

参考资料

Head First设计模式
https://github.com/faif/python-patterns
https://www.runoob.com/design-pattern/strategy-pattern.html

 类似资料: