结构型模式(7种):适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式
1、适配器模式
- 适配器模式
- 内容:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
- 两种实现方式:
- 类适配器:使得多继承
- 对象适配器:使用组合
- 角色:
- 目标接口
- 待适配的类
- 适配器
- 适用场景
- 想使用一个已存在的类,而它的接口不符合你的要求
- (对象适配器)想使用一些已经存在的子类,但不可能对每一个都进行子类化以匹配它们的接口,对象适配器可以适配它的父类接口
ethod
def pay(self, money):
pass
class Aipay(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(ApplePay())
p.pay(100)
2、桥模式
- 桥模式:
- 内容:将一个事物的两个维度分离,使其都可以独立的变化
- 角色:
- 抽象
- 细化抽象
- 实现者
- 具体实现者
- 应用场景:
- 当两个事物有两个维度上的表现,两个维度都可能扩展时
- 优点
- 抽象和实现相分离
- 优秀的扩展能力
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)
class Red(Color):
def paint(self, shape):
print("红色的%s" % shape.name)
class Green(Color):
def paint(self, shape):
print("绿色的%s" % shape.name)
shape = Rectangle(Red())
shape.draw()
3、 组合模式
- 组合模式:
- 内容:将对象组合成树形结构,以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性
- 角色:
- 抽象组件
- 叶子组件
- 复合组件
- 客户端
- 适用场景:
- 表示对象的“部分-整体”层次结构(特别是结构是递归的)
- 希望用户忽略组合对象和单个对象的不同,用户统一的使用组合结构中的所有对象
- 优点:
- 定义了包含基本对象和组合对象的类层次结构
- 简化客户端代码,即客户端可以一致的使用组合对象和单个对象
- 更容易增加新类型的组件
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("-----复合图像-----")
l = Line(Point(1,1), Point(2,2))
print(l)
4、外观模式
- 外观模式:
- 内容:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这一接口使得这一子系统更加容易使用
- 角色:
- 外观
- 子系统类
- 优点:
- 减少系统相互依赖
- 提高了灵活性
- 提高了安全性
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()
# client
computer = Computer()
computer.run()
computer.stop()
5、代理模式
- 代理模式
- 内容:为其他对象提供一种代理以控制对这个对象的访问
- 应用场景:
- 远程代理:为远程的对象提供代理
- 虚代理:根据需要创建很大的对象
- 保护代理:控制对原始对象的访问,用于对象有不同访问权限时
- 角色:
- 抽象实体
- 实体
- 代理
- 优点:
- 远程代理:可以隐藏对象位于远程地址空间的事实
- 虚代理:可以进行优化,例如根据要求创建代理
- 保护代理:允许在访问一个对象时有一些附加的内务处理
from abc import ABCMeta, abstractmethod
class Subject(metaclass=ABCMeta):
@abstractmethod
def get_content(self):
pass
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 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("无写入权限")