Python常见设计模式2: 结构型模式
文章目录
- 适配器模式
- 桥接模式
- 组合模式
- 外观模式
- 代理模式
适配器模式
- 将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- 两种实现方式:
- 类适配器:使用多继承
- 对象适配器:使用组合
# 适配器模式
from abc import ABCMeta, abstractmethodclass Payment(metaclass=ABCMeta):@abstractmethoddef pay(self, money):passclass 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 NewBankPay(Payment, BankPay):
# def pay(self, money):
# self.cost(money)# 对象适配器
class PaymentAdapter(Payment):def __init__(self, payment):self.payment = paymentdef pay(self, money):self.payment.cost(money)p = PaymentAdapter(BankPay())
p.pay(100)
桥接模式
- 将一个事物的两个维度分离,使其都可以独立地变化。
from abc import ABCMeta, abstractmethodclass Shape(metaclass=ABCMeta):def __init__(self, color):self.color = color@abstractmethoddef draw(self):passclass Color(metaclass=ABCMeta):@abstractmethoddef paint(self, shape):passclass Rectangle(Shape):name = "长方形"def draw(self):# TODO:矩形逻辑self.color.paint(self)class Circle(Shape):name = "圆形"def draw(self):# TODO:原型逻辑self.color.paint(self)class Red(Color):def __init__(self,shape):self.shape=shapedef paint(self):print("红色的%s" % self.shape.name)class Green(Color):def __init__(self,shape):self.shape=shapedef paint(self):print("绿色的%s" % self.shape.name)shape = Rectangle(Red())
shape.draw()shape2 = Circle(Green())
shape2.draw()
组合模式
- 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式是用户对单个对象和组合对象的使用都具有一致性。
- 角色:
- 抽象组件(Component)
- 叶子组件(Leaf)
- 复合组件(Composite)
- 客户端(Client)
from abc import ABCMeta, abstractmethod
# 抽象组件class Graphic(metaclass=ABCMeta):@abstractmethoddef draw(self):pass# 叶子组件
class Point(Graphic):def __init__(self, x, y):self.x = xself.y = ydef __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 = p1self.p2 = p2def __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("*"* 100)print("----复合图形 start----")for g in self.children:g.draw()print("----复合图形 end----")# 线段
l = Line(Point(1, 1), Point(2, 2))
print(l)# 点跟线组合
p1 = Point(2, 3)
l1 = Line(Point(2, 4), Point(6, 7))
l2 = Line(Point(1, 5), Point(2, 8))
pic1 = Picture([p1, l1, l2])
# pic1.draw()# pic1跟 pic2再次组合
l3 = Line(Point(2, 4), Point(6, 7))
l4 = Line(Point(1, 5), Point(2, 8))
pic2 = Picture([l3, l4])
pic3 = Picture([pic1, pic2])
pic3.draw()
# 此处csdn运行代码可能出问题,理论上应该有三次**********
外观模式
- 为子系统的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
- 角色:
- 外观(Facade)
- 子系统类(Sub system 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: # Facadedef __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.memory.stop()self.disk.stop()self.cpu.stop()computer = Computer()
computer.run()
print(f"计算机正在运行。。。")
computer.stop()
代理模式
- 为其他对象提供一种代理以控制对这个对象的访问
- 应用场景:
- 远程代理:为远程的对象提供代理
- 虚代理:可在需要时才创建对象,减少内存消耗
- 保护代理:控制对原始对象的访问,用于对象有不同访问权限时
建议在py源文件同级目录下创建一个test.txt文件
Initial Context.
"""
角色:抽象实体(Subject)实体(RealSubject)代理(Proxy)
"""from abc import ABCMeta, abstractmethodclass Subject(metaclass=ABCMeta):@abstractmethoddef get_content(self):pass@abstractmethoddef set_content(self, content):passclass RealSubject(Subject):def __init__(self, filename):self.filename = filename# 尝试读取文件,如果文件不存在则初始化为空内容try:with open(filename, 'r') as f:self.content = f.read()except FileNotFoundError:self.content = ""def get_content(self):return self.contentdef set_content(self, content, new_filename=None):# 如果提供了新文件名,则更新当前实例的文件名if new_filename:self.filename = new_filename# 写入内容(如果文件不存在会自动创建)with open(self.filename, 'w') as f:f.write(content)self.content = contentclass VirtualProxy(Subject):def __init__(self, filename):self.filename = filenameself.subj = Nonedef get_content(self):if not self.subj:self.subj = RealSubject(self.filename)return self.subj.get_content()def set_content(self, content):if not self.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.set_content("Testing Context.")
print(subj.get_content())print("---- VirtualProxy")
v_subj = VirtualProxy("test.txt")
print(v_subj.get_content())print("---- ProtectedProxy")
p_subj = ProtectedProxy("test.txt")
print(p_subj.get_content())
# p_subj.set_content("aaa")
# 会输出PermissionError