简介 转载于:python设计模式 。
设计模式简介
设计模式:对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。 “四人帮”(Gang of Four, GoF):Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 《设计模式:可复用面向对象软件的基础》
复习:面向对象
面向对象的三大特性:
封装:将数据、方法封装到一个类里;具有共有和私有属性。
继承:多个类之间复用代码使用继承。
多态:python本身就是一门多态语言,不用程序员去考虑多态,语言特性自己做了。
接口
1 2 接口:若干抽象方法的集合。` `作用:限制实现接口的类必须按照接口给定的调用方式实现这些方法;对高层模块隐藏了类的内部实现。
1 2 3 4 @abstractmethod:抽象方法,含abstractmethod方法的类不能实例化,继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写` `@property:方法伪装属性,方法返回值及属性值,被装饰方法不能有参数,必须实例化后调用,类不能调用` `@classmethod:类方法,可以通过实例对象和类对象调用,被该函数修饰的方法第一个参数代表类本身常用cls,被修饰函数内可调用类属性,不能调用实例属性` `@staticmethod:静态方法,可以通过实例对象和类对象调用,被装饰函数可无参数,被装饰函数内部通过类名.属性引用类属性或类方法,不能引用实例属性
1 2 3 4 5 6 from abc import ABCMeta, abstractmethodclass Payment (metaclass=ABCMeta): @abstractmethod def pay (self, money ): pass
面向对象设计SOLID原则
1 2 3 4 5 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。` `里氏替换原则:所有引用父类的地方必须能透明地使用其子类的对象。` `依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。 接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。` `单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
设计模式分类
1 2 3 创建型模式(5种)`:`工厂方法模式、抽象工厂模式、创建者模式`、原型模式、`单例模式` `结构型模式(7种)`:`适配器模式、桥模式、组合模式`、装饰模式、`外观模式`、享元模式、`代理模式` `行为型模式(11种)`:解释器模式、`责任链模式`、命令模式、迭代器模式、中介者模式、备忘录模式、`观察者模式`、状态模式、`策略模式`、访问者模式、`模板方法模式
创建型模式 简单工厂模式(掌握)
内容:不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。
角色:
工厂角色(Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)
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 from abc import ABCMeta, abstractmethodclass Payment (metaclass=ABCMeta): @abstractmethod def pay (self, money ): pass class Alipay (Payment ): def __init__ (self, use_huabei=False ): self.use_huaei = use_huabei def pay (self, money ): if self.use_huaei: print ("花呗支付%d元." % money) else : print ("支付宝余额支付%d元." % money) class WechatPay (Payment ): def pay (self, money ): print ("微信支付%d元." % money) class PaymentFactory : def create_payment (self, method ): if method == 'alipay' : return Alipay() elif method == 'wechat' : return WechatPay() elif method == 'huabei' : return Alipay(use_huabei=True ) else : raise TypeError("No such payment named %s" % method) pf = PaymentFactory() p = pf.create_payment('huabei' ) p.pay(100 )
优点:
缺点:
违反了单一职责原则,将创建逻辑几种到一个工厂类里
当添加新产品时,需要修改工厂类代码,违反了开闭原则
由此方法引出工厂方法模式
工厂方法模式(使用较多)
内容:定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。 角色:
抽象工厂角色(Creator)
具体工厂角色(Concrete Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)
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 from abc import ABCMeta, abstractmethodclass Payment (metaclass=ABCMeta): @abstractmethod def pay (self, money ): pass class Alipay (Payment ): def __init__ (self, use_huabei=False ): self.use_huaei = use_huabei def pay (self, money ): if self.use_huaei: print ("花呗支付%d元." % money) else : print ("支付宝余额支付%d元." % money) class WechatPay (Payment ): def pay (self, money ): print ("微信支付%d元." % money) class BankPay (Payment ): def pay (self, money ): print ("银行卡支付%d元." % money) class PaymentFactory (metaclass=ABCMeta): @abstractmethod def create_payment (self ): pass class AlipayFactory (PaymentFactory ): def create_payment (self ): return Alipay() class WechatPayFactory (PaymentFactory ): def create_payment (self ): return WechatPay() class HuabeiFactory (PaymentFactory ): def create_payment (self ): return Alipay(use_huabei=True ) class BankPayFactory (PaymentFactory ): def create_payment (self ): return BankPay() pf = HuabeiFactory() p = pf.create_payment() p.pay(100 )
优点:
每个具体产品都对应一个具体工厂类,不需要修改工厂类代码
隐藏了对象创建的实现细节
缺点:
每增加一个具体产品类,就必须增加一个相应的具体工厂类
抽象工厂模式(使用较少)
内容:定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象。 例:生产一部手机,需要手机壳、CPU、操作系统三类对象进行组装,其中每类对象都有不同的种类。对每个具体工厂,分别生产一部手机所需要的三个对象。 相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品。
角色:
抽象工厂角色(Creator)
具体工厂角色(Concrete Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)
客户端(Client)
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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 from abc import abstractmethod, ABCMetaclass PhoneShell (metaclass=ABCMeta): @abstractmethod def show_shell (self ): pass class CPU (metaclass=ABCMeta): @abstractmethod def show_cpu (self ): pass class OS (metaclass=ABCMeta): @abstractmethod def show_os (self ): pass class PhoneFactory (metaclass=ABCMeta): @abstractmethod def make_shell (self ): pass @abstractmethod def make_cpu (self ): pass @abstractmethod def make_os (self ): pass class SmallShell (PhoneShell ): def show_shell (self ): print ("普通手机小手机壳" ) class BigShell (PhoneShell ): def show_shell (self ): print ("普通手机大手机壳" ) class AppleShell (PhoneShell ): def show_shell (self ): print ("苹果手机壳" ) class SnapDragonCPU (CPU ): def show_cpu (self ): print ("骁龙CPU" ) class MediaTekCPU (CPU ): def show_cpu (self ): print ("联发科CPU" ) class AppleCPU (CPU ): def show_cpu (self ): print ("苹果CPU" ) class Android (OS ): def show_os (self ): print ("Android系统" ) class IOS (OS ): def show_os (self ): print ("iOS系统" ) class MiFactory (PhoneFactory ): def make_cpu (self ): return SnapDragonCPU() def make_os (self ): return Android() def make_shell (self ): return BigShell() class HuaweiFactory (PhoneFactory ): def make_cpu (self ): return MediaTekCPU() def make_os (self ): return Android() def make_shell (self ): return SmallShell() class IPhoneFactory (PhoneFactory ): def make_cpu (self ): return AppleCPU() def make_os (self ): return IOS() def make_shell (self ): return AppleShell() class Phone : def __init__ (self, cpu, os, shell ): self.cpu = cpu self.os = os self.shell = shell def show_info (self ): print ("手机信息:" ) self.cpu.show_cpu() self.os.show_os() self.shell.show_shell() def make_phone (factory ): cpu = factory.make_cpu() os = factory.make_os() shell = factory.make_shell() return Phone(cpu, os, shell) p1 = make_phone(IPhoneFactory()) p1.show_info()
优点:
将客户端与类的具体实现相分离
每个工厂创建了一个完整的产品系列,使得易于交换产品系列
有利于产品的一致性(即产品之间的约束关系)
缺点:
建造者模式 内容:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 角色:
抽象建造者(Builder)
具体建造者(Concrete Builder)
指挥者(Director)
产品(Product)
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 from abc import ABCMeta, abstractmethodclass Player : def __init__ (self, face=None , body=None , arm=None , leg=None ): self.face = face self.body = body self.arm = arm self.leg = leg def __str__ (self ): return "%s, %s, %s, %s" % (self.face, self.body, self.arm, self.leg) class PlayerBuilder (metaclass=ABCMeta): @abstractmethod def build_face (self ): pass @abstractmethod def build_body (self ): pass @abstractmethod def build_arm (self ): pass @abstractmethod def build_leg (self ): pass class SexyGirlBuilder (PlayerBuilder ): def __init__ (self ): self.player = Player() def build_face (self ): self.player.face = "漂亮脸蛋" def build_body (self ): self.player.body = "苗条" def build_arm (self ): self.player.arm = "漂亮胳膊" def build_leg (self ): self.player.leg = "大长腿" class Monster (PlayerBuilder ): def __init__ (self ): self.player = Player() def build_face (self ): self.player.face = "怪兽脸" def build_body (self ): self.player.body = "怪兽身材" def build_arm (self ): self.player.arm = "长毛的胳膊" def build_leg (self ): self.player.leg = "长毛的腿" class PlayerDirector : def build_player (self, builder ): builder.build_body() builder.build_face() builder.build_arm() builder.build_leg() return builder.player builder = Monster() director = PlayerDirector() p = director.build_player(builder) print (p)
建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别是建造者模式着重一步步构造一个复杂对象,而抽象工厂模式着重于多个系列的产品对象。 优点:
隐藏了一个产品的内部结构和装配过程
将构造代码与表示代码分开
可以对构造过程进行更精细的控制
单例模式(常用)
内容:保证一个类只有一个实例,并提供一个访问它的全局访问点。 角色:
优点:
对唯一实例的受控访问
单例相当于全局变量,但防止了命名空间被污染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from abc import abstractmethod, ABCMetaclass Singleton : def __new__ (cls, *args, **kwargs ): if not hasattr (cls, "_instance" ): cls._instance = super (Singleton, cls).__new__(cls) return cls._instance class MyClass (Singleton ): def __init__ (self, a ): self.a = a a = MyClass(10 ) b = MyClass(20 ) print (a.a)print (b.a)print (id (a), id (b))
注意:在多线程下的问题和解决手段
创建型模式小结 抽象工厂模式和建造者模式相比于简单工厂模式和工厂方法模式而言更灵活也更复杂。 通常情况下、设计以简单工厂模式或工厂方法模式开始,当你发现设计需要更大的灵活性时,则像更复杂的设计模式演化。
结构型模式 适配器模式
内容:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 两种实现方式:
角色:
目标接口(Target)
待适配的类(Adaptee)
适配器(Adapter)
适用场景:
想使用一个已经存在的类,而它的接口不符合你的要求
(对象适配器)想使用一些已经存在的子类,但不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
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 from abc import ABCMeta, abstractmethodclass Payment (metaclass=ABCMeta): @abstractmethod def pay (self, money ): pass class Alipay (Payment ): def pay (self, money ): print ("支付宝支付%d元." % money) class WechatPay (Payment ): def pay (self, money ): print ("微信支付%d元." % money) class BankPay : def cost (self, money ): print ("银联支付%d元." % money) class ApplePay : def cost (self, money ): print ("苹果支付%d元." % money) class PaymentAdapter (Payment ): def __init__ (self, payment ): self.payment = payment def pay (self, money ): self.payment.cost(money) p = PaymentAdapter(BankPay()) p.pay(100 )
注意:组合 or 继承:根据个人使用经验来。一般继承层数少的话,可以使用继承,否则组合是比较好的选择
桥模式 内容:将一个事物的两个维度分离,使其都可以独立地变化
角色:
抽象(Abstraction)
细化抽象(RefinedAbstraction)
实现者(Implementor)
具体实现者(ConcreteImplementor
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 from abc import ABCMeta, abstractmethodclass Shape (metaclass=ABCMeta): def __init__ (self, color ): self.color = color @abstractmethod def draw (self ): pass class Color (metaclass=ABCMeta): @abstractmethod def paint (self, shape ): pass class Rectangle (Shape ): name = "长方形" def draw (self ): self.color.paint(self) class Circle (Shape ): name = "圆形" def draw (self ): self.color.paint(self) class Line (Shape ): name = "直线" def draw (self ): self.color.paint(self) class Red (Color ): def paint (self, shape ): print ("红色的%s" % shape.name) class Green (Color ): def paint (self, shape ): print ("绿色的%s" % shape.name) class Blue (Color ): def paint (self, shape ): print ("蓝色的%s" % shape.name) shape = Line(Blue()) shape.draw() shape2 = Circle(Green()) shape2.draw()
应用场景:
优点:
组合模式 内容:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 角色:
抽象组件(Component)
叶子组件(Leaf)
复合组件(Composite)
客户端(Client)
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 from abc import ABCMeta, abstractmethodclass Graphic (metaclass=ABCMeta): @abstractmethod def draw (self ): pass class Point (Graphic ): def __init__ (self, x, y ): self.x = x self.y = y def __str__ (self ): return "点(%s, %s)" % (self.x, self.y) def draw (self ): print (str (self)) class Line (Graphic ): def __init__ (self, p1, p2 ): self.p1 = p1 self.p2 = p2 def __str__ (self ): return "线段[%s, %s]" % (self.p1, self.p2) def draw (self ): print (str (self)) class Picture (Graphic ): def __init__ (self, iterable ): self.children = [] for g in iterable: self.add(g) def add (self, graphic ): self.children.append(graphic) def draw (self ): print ("------复合图形------" ) for g in self.children: g.draw() print ("------复合图形------" ) p1 = Point(2 ,3 ) l1 = Line(Point(3 ,4 ), Point(6 ,7 )) l2 = Line(Point(1 ,5 ), Point(2 ,8 )) pic1 = Picture([p1, l1, l2]) p2 = Point(4 ,4 ) l3 = Line(Point(1 ,1 ), Point(0 ,0 )) pic2 = Picture([p2, l3]) pic = Picture([pic1, pic2]) pic.draw()
适用场景:
表示对象的“部分-整体”层次结构(特别是结构是递归的)
希望用户忽略组合对象与单个对象的不同,用户统一地使用组合结构中的所有对象
优点:
定义了包含基本对象和组合对象的类层次结构
简化客户端代码,即客户端可以一致地使用组合对象和单个对象
更容易增加新类型的组件
外观模式 内容:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 角色:
外观(facade)
子系统类(subsystem classes)
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 class CPU : def run (self ): print ("CPU开始运行" ) def stop (self ): print ("CPU停止运行" ) class Disk : def run (self ): print ("硬盘开始工作" ) def stop (self ): print ("硬盘停止工作" ) class Memory : def run (self ): print ("内存通电" ) def stop (self ): print ("内存断电" ) class Computer : def __init__ (self ): self.cpu = CPU() self.disk = Disk() self.memory = Memory() def run (self ): self.cpu.run() self.disk.run() self.memory.run() def stop (self ): self.cpu.stop() self.disk.stop() self.memory.stop() computer = Computer() computer.run() computer.stop()
优点:
代理模式 内容:为其他对象提供一种代理以控制对这个对象的访问。 应用场景:
远程代理:为远程的对象提供代理,例如HSF
虚代理:根据需要创建很大的对象
保护代理:控制对原始对象的访问,用于对象有不同访问权限时
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 from abc import ABCMeta, abstractmethodclass Subject (metaclass=ABCMeta): @abstractmethod def get_content (self ): pass @abstractmethod def set_content (self, content ): pass class RealSubject (Subject ): def __init__ (self, filename ): self.filename = filename f = open (filename, 'r' , encoding='utf-8' ) print ("读取文件内容" ) self.content = f.read() f.close() def get_content (self ): return self.content def set_content (self, content ): f = open (self.filename, 'w' , encoding='utf-8' ) f.write(content) f.close() class VirtualProxy (Subject ): """虚代理""" def __init__ (self, filename ): self.filename = filename self.subj = None def get_content (self ): if not self.subj: self.subj = RealSubject(self.filename) return self.subj.get_content() def set_content (self, content ): if not subj: self.subj = RealSubject(self.filename) return self.subj.set_content(content) class ProtectedProxy (Subject ): def __init__ (self, filename ): self.subj = RealSubject(filename) def get_content (self ): return self.subj.get_content() def set_content (self, content ): raise PermissionError("无写入权限" ) subj = ProtectedProxy("test.txt" ) print (subj.get_content())subj.set_content("abc" )
角色:
抽象实体(Subject)
实体(RealSubject)
代理(Proxy)
优点:
远程代理:可以隐藏对象位于远程地址空间的事实
虚代理:可以进行优化,例如根据要求创建对象
保护代理:允许在访问一个对象时有一些附加的内务处理
行为型模式 责任链模式 内容:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 角色:
抽象处理者(Handler)
具体处理者(ConcreteHandler)
客户端(Client)
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 from abc import ABCMeta, abstractmethodclass Handler (metaclass=ABCMeta): @abstractmethod def handle_leave (self, day ): pass class GeneralManager (Handler ): def handle_leave (self, day ): if day <= 10 : print ("总经理准假%d天" % day) else : print ("你还是辞职吧" ) class DepartmentManager (Handler ): def __init__ (self ): self.next = GeneralManager() def handle_leave (self, day ): if day <= 5 : print ("部门经理准假%s天" % day) else : print ("部门经理职权不足" ) self.next .handle_leave(day) class ProjectDirector (Handler ): def __init__ (self ): self.next = DepartmentManager() def handle_leave (self, day ): if day <= 3 : print ("项目主管准假%d天" % day) else : print ("项目主管职权不足" ) self.next .handle_leave(day) day = 12 h = ProjectDirector() h.handle_leave(day)
适用场景:
有多个对象可以处理一个请求,哪个对象处理由运行时决定
在不明确接收者的情况下,向多个对象中的一个提交一个请求
优点:
降低耦合度:一个对象无需知道是其他哪一个对象处理其请求
注意:现有大多数的习惯都将执行类的逻辑放在外层,可以参考责任链放在执行类里面,更符合面向对象,也更符合开闭原则
观察者模式(使用较多) 内容:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。观察者模式又称“发布-订阅”模式 角色: 抽象主题(Subject) 具体主题(ConcreteSubject)——发布者 抽象观察者(Observer) 具体观察者(ConcreteObserver)——订阅者
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 from abc import ABCMeta, abstractmethodclass Observer (metaclass=ABCMeta): @abstractmethod def update (self, notice ): pass class Notice : def __init__ (self ): self.observers = [] def attach (self, obs ): self.observers.append(obs) def detach (self, obs ): self.observers.remove(obs) def notify (self ): for obs in self.observers: obs.update(self) class StaffNotice (Notice ): def __init__ (self, company_info=None ): super ().__init__() self.__company_info = company_info @property def company_info (self ): return self.__company_info @company_info.setter def company_info (self, info ): self.__company_info = info self.notify() class Staff (Observer ): def __init__ (self ): self.company_info = None def update (self, notice ): self.company_info = notice.company_info notice = StaffNotice("初始公司信息" ) notice.company_info s1 = Staff() s2 = Staff() notice.attach(s1) notice.attach(s2) print (s1.company_info)notice.company_info = "公司今年业绩非常好,给大家发奖金!!!" print (s1.company_info)print (s2.company_info)notice.detach(s2) notice.company_info = "公司明天放假!!!" print (s1.company_info)print (s2.company_info)
适用场景:
当一个抽象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们可以各自独立地改变和复用。
当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
优点:
策略模式 内容:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 角色:
抽象策略(Strategy)
具体策略(ConcreteStrategy)
上下文(Context)
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 from abc import ABCMeta,abstractmethodclass Strategy (metaclass=ABCMeta): @abstractmethod def execute (self, data ): pass class FastStrategy (Strategy ): def execute (self, data ): print ("用较快的策略处理%s" % data) class SlowStrategy (Strategy ): def execute (self, data ): print ("用较慢的策略处理%s" % data) class Context : def __init__ (self, strategy, data ): self.data = data self.strategy = strategy def set_strategy (self, strategy ): self.strategy = strategy def do_strategy (self ): self.strategy.execute(self.data) data = "[...]" s1 = FastStrategy() s2 = SlowStrategy() context = Context(s1, data) context.do_strategy() context.set_strategy(s2) context.do_strategy()
优点:
定义了一系列可重用的算法和行为
消除了一些条件语句
可以提供相同行为的不同实现
缺点:
模板方法模式 内容:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 角色:
抽象类(AbstractClass):定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。
具体类(ConcreteClass):实现原子操作
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 from abc import ABCMeta, abstractmethodfrom time import sleepclass Window (metaclass=ABCMeta): @abstractmethod def start (self ): pass @abstractmethod def repaint (self ): pass @abstractmethod def stop (self ): pass def run (self ): self.start() while True : try : self.repaint() sleep(1 ) except KeyboardInterrupt: break self.stop() class MyWindow (Window ): def __init__ (self, msg ): self.msg = msg def start (self ): print ("窗口开始运行" ) def stop (self ): print ("窗口结束运行" ) def repaint (self ): print (self.msg) MyWindow("Hello..." ).run()
适用场景:
一次性实现一个算法的不变的部分
各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复
控制子类扩展