定义
代理模式的模型抽象
代码框架
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class Subject(metaclass=ABCMeta):
"""主题类"""
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
@abstractmethod
def request(self, content = ''):
pass
class RealSubject(Subject):
"""真实主题类"""
def request(self, content):
print("RealSubject todo something...")
class ProxySubject(Subject):
"""代理主题类"""
def __init__(self, name, subject):
super().__init__(name)
self._realSubject = subject
def request(self, content = ''):
self.preRequest()
if(self._realSubject is not None):
self._realSubject.request(content)
self.afterRequest()
def preRequest(self):
print("preRequest")
def afterRequest(self):
print("afterRequest")
类图
基于框架的实现
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class Subject(metaclass=ABCMeta):
"""主题类"""
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
@abstractmethod
def request(self, content=''):
pass
class RealSubject(Subject):
"""真实主题类"""
def request(self, content):
print("RealSubject todo something...")
class ProxySubject(Subject):
"""代理主题类"""
def __init__(self, name, subject):
super().__init__(name)
self._realSubject = subject
def request(self, content=''):
self.preRequest()
if (self._realSubject is not None):
self._realSubject.request(content)
self.afterRequest()
def preRequest(self):
print("preRequest")
def afterRequest(self):
print("afterRequest")
class TonyReception(Subject):
"""Tony接收"""
def __init__(self, name, phoneNum):
super().__init__(name)
self.__phoneNum = phoneNum
def getPhoneNum(self):
return self.__phoneNum
def request(self, content):
print("货物主人:%s,手机号:%s" % (self.getName(), self.getPhoneNum()))
print("接收到一个包裹,包裹内容:%s" % str(content))
class WendyReception(ProxySubject):
"""Wendy代收"""
def __init__(self, name, receiver):
super().__init__(name, receiver)
def preRequest(self):
print("我是%s的朋友,我来帮他代收快递!" % (self._realSubject.getName() + ""))
def afterRequest(self):
print("代收人:%s" % self.getName())
# Test
# =======================================================================================================================
def testReceiveParcel():
tony = TonyReception("Tony", "18512345678")
print("Tony接收:")
tony.receive("雪地靴")
print()
print("Wendy代收:")
wendy = WendyReception("Wendy", tony)
wendy.receive("雪地靴")
def testProxy():
realObj = RealSubject('RealSubject')
proxyObj = ProxySubject('ProxySubject', realObj)
proxyObj.request()
def testReceiveParcel2():
tony = TonyReception("Tony", "18512345678")
print("Tony接收:")
tony.request("雪地靴")
print()
print("Wendy代收:")
wendy = WendyReception("Wendy", tony)
wendy.request("雪地靴")
testReceiveParcel2()
模型说明
- 设计要点
- 主题(Subject):定义操作、活动、任务的接口类。
- 真实主题(RealSubject):真正完成操作、活动、任务的具体类。
- 代理主题(ProxySubject):代替真实主题完成操作、活动、任务的代理类。
- 优缺点
- 优点:
- 代理模式能够协调调用者和被调用者,在一定程度上降低系统的耦合度。
- 可以灵活地隐藏被代理对象的部分功能和服务,也可以增加额外的功能和服务。
- 缺点:
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
应用场景
- 不想或者不能直接引用一个对象时,如在移动端加载网页信息时,因为下载真实大图比较耗费流量、影响性能,可以用一个小图代替进行渲染(用一个代理对象去下载小图),在真正点击图片时,才下载大图,显示大图效果。还有 HTML 中的占位符,其实也是代理模式的思想。
- 想对一个对象的功能进行加强时,如在字体(Font)渲染时,对粗体(BoldFont)进行渲染时,可使用字体 Font 对象进行代理,只要在对 Font 进行渲染后进行加粗的操作即可。
- 各种特殊用途的代理:远程代理、虚拟代理、Copy-on-Write 代理、保护(Protect or Access)代理、Cache 代理、防火墙(Firewall)代理、同步化(Synchronization)代理、智能引用(Smart Reference)代理。