类中根据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: ...
对象版的: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
封装执行一个动作或者触发一个时间的所有信息
例子:
MoveFileCommand
变量src、dest
函数 execute、undo、rename
iterator(迭代器)
遍历容器并获取元素
Mediator(中介者)
系统中的对象通过一个中介交流而不是直接交流。减少对象依赖,因此减少耦合。
例子:用户通过聊天室聊天。
保存一个对象之前的状态
实例
定义用函数,返回函数名(闭包)
定义用类,可用作装饰器。初始化保留函数,__get__方法返回闭包,state状态就保留着,失败直接恢复。
维护依赖列表项,并在状态改变时唤醒他们。
基类——观察者管理列
value 观察列表
方法:attach:添加观察者;detach:减少观察者;notify:唤醒观察者
数据类:继承基类
观察者类,处理观察值。
消息订阅与发布。类似订报纸。
实例
Provider 消息订阅、取消、新增消息以及分发功能
Publisher 发布消息,保留一个provider实例
Subscriber 订阅消息
记录一个类的所有子类
把生成的实例记录到字典中,通过键值(如类名可找到相应的实例)
通过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())
定义: 状态模式允许对象在内部状态改变时改变他的行为,对象看起来好像修改了他的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
何时使用:代码中包含大量与对象状态有关的条件语句。
注:可用有限状态机DFA实现。
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
例子:订单打折,有多种订单打折策略。传入不同函数,如10%打折,促销打折。
意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
何时使用:有一些通用的方法。
意图:主要将数据结构与数据操作分离。
主要解决:稳定的数据结构和易变的操作耦合问题。
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。
如何解决:在被访问的类里面加一个对外提供接待访问者的接口。
使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
value:类
borg(MonoState) 单一状态模式
单例的一种实现方式
共享状态
实例:数据库连接管理
实现:self.dict = self.__shared_state # __shared_state = {} 为类变量
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
延迟表达式计算直到值需要时,并且避免重复计算
实现:封装方法,作为装饰器。
意图:在创建对象比较昂贵,或者对于特定类型能够创建的对象数目有限制时,管理对象的重用。
例子
queue.Queue
prototype原型模式
意图:减少应用程序所需的类的数量
主要解决:在运行期建立和删除原型。
何时使用:
使用场景
使对象复合获得和继承相同的代码重用
在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。
将不同的接口整合到一个特定的API而不需要修改原来的对象。
目的:将抽象部分与它的实现部分分离,使他们都可以独立地变化。
“将抽象部分与它的实现部分分离”指实现系统可能有多个角度分类,每一种分类都可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
好处
主要功能:将对象组合成树形结构以表示“部分-整体”的层次结构。这可以使得用户在使用单个对象和组合对象时有一致性。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用:
UML类图参考 https://www.cnblogs.com/zyrblog/p/9237943.html
用处:动态添加新功能而不改变原有实现。不像继承,新功能添加到所有子类,而是只添加到特定的一个对象。
实例:为字符串添加xml格式的tag
目的:通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。
好处:该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
例子:台式机开机只需要按一个开机按钮。
意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
适用性
用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。
实现
前端控制器(Front Controller) - 处理应用程序所有类型请求的单个处理程序,应用程序可以是基于 web 的应用程序,也可以是基于桌面的应用程序。
调度器(Dispatcher) - 前端控制器可能使用一个调度器对象来调度请求到相应的具体处理程序。
视图(View) - 视图是为请求而创建的对象。
MVC模型-视图-控制器模式
用于应用程序的分层开发
意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制。
例子:客户——代理沟通——经理
实现控制反转
如果一个类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