sjms-3 结构型模式
结构型模式
适配器模式
内容:将一个类的接口转换成客户希望的另一个接口。适配器模式使
得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
两种实现方式:
类适配器:使用多继承
对象适配器:使用组合
角色:
目标接口(Target)
待适配的类(Adaptee)
适配器(Adapter)
适用场景:
想使用一个已经存在的类,而它的接口不符合你的要求(对象适配器)想使用一些已经存在的子类,但不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): # abstract class @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 NewBankPay(Payment, BankPay): # def pay(self, money): # self.cost(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) # 组合 # class A: # pass # # class B: # def __init__(self): # self.a = A()
桥模式
内容:
将一个事物的两个维度分离,使其都可以独立地变化。
角色:
抽象(Abstraction)
细化抽象(RefinedAbstraction)
实现者(Implementor)
具体实现者(ConcreteImplementor)
应用场景:
当事物有两个维度上的表现,两个维度都可能扩展时。
优点:
抽象和实现相分离
优秀的扩展能力
from abc import ABCMeta, abstractmethod class 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) # 调用color 对象的paint并把self形状对象传过去,方便color的paint打印 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()) # 先把color对象传过来,以便draw调用 # (其实draw调用的时候,是调用color的paint方法,并把shape对象传给paint让它去调用shape的name) shape2.draw() # 两个维度都可以扩展
组合模式
内容:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
角色:
抽象组件(Component)
叶子组件(Leaf)
复合组件(Composite)
客户端(Client)
from abc import ABCMeta, abstractmethod # 抽象组件 class 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() """ ------复合图形------ ------复合图形------ 点(2, 3) 线段[点(3, 4), 点(6, 7)] 线段[点(1, 5), 点(2, 8)] ------复合图形------ ------复合图形------ 点(4, 4) 线段[点(1, 1), 点(0, 0)] ------复合图形------ ------复合图形------ """
适用场景:
表示对象的“部分-整体”层次结构(特别是结构是递归的)
希望用户忽略组合对象与单个对象的不同,用户统一地使用组合结构中的所有对象
优点:
定义了包含基本对象和组合对象的类层次结构
简化客户端代码,即客户端可以一致地使用组合对象和单个对象
更容易增加新类型的组件
外观模式
内容:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
角色:
外观(facade)
子系统类(subsystem classes)
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: # Facade 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()
优点:
减少系统相互依赖
提高了灵活性
提高了安全性
代理模式
内容:为其他对象提供一种代理以控制对这个对象的访问。
应用场景:
远程代理:为远程的对象提供代理
虚代理:根据需要创建很大的对象
保护代理:控制对原始对象的访问,用于对象有不同访问权限时
from abc import ABCMeta, abstractmethod class 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 with open(filename, 'r', encoding='utf-8') as f: print("读取文件内容") self.content = f.read() def get_content(self): return self.content def set_content(self, content): with open(self.filename, 'w', encoding='utf-8') as f: f.write(content) 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) # 在调用get_content 时才真正去打开文件 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 = RealSubject("test.txt") #subj.get_content() subj = ProtectedProxy("test.txt") print(subj.get_content()) # subj.set_content("abc")
角色:
抽象实体(Subject)
实体(RealSubject)
代理(Proxy)
优点:
远程代理:可以隐藏对象位于远程地址空间的事实
虚代理:可以进行优化,例如根据要求创建对象
保护代理:允许在访问一个对象时有一些附加的内务处理