8.设计模式之六:代理模式【结构型模式】

结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。python

因为组合关系或聚合关系比继承关系耦合度低,知足“合成复用原则”,因此对象结构型模式比类结构型模式具备更大的灵活性。安全

在有些状况下,一个客户不能或者不想直接访问另外一个对象,这时须要找一个中介帮忙完成某项任务,这个中介就是代理对象。例如,购买火车票不必定要去火车站买,能够经过 12306 网站或者去火车票代售点买。服务器

定义与特色

代理模式的定义:因为某些缘由须要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象做为访问对象和目标对象之间的中介。布局

代理模式的主要优势有:post

  • 代理模式在客户端与目标对象之间起到一个中介做用和保护目标对象的做用;
  • 代理对象能够扩展目标对象的功能;
  • 代理模式能将客户端与目标对象分离,在必定程度上下降了系统的耦合度;

其主要缺点是:性能

  • 在客户端和目标对象之间增长一个代理对象,会形成请求处理速度变慢;
  • 增长了系统的复杂度;

结构与实现

代理模式的结构比较简单,主要是经过定义一个继承抽象主题的代理来包含真实主题,从而实现对真实主题的访问,下面来分析其基本结构和实现方法。网站

代理模式的主要角色以下:spa

  1. 抽象主题(Subject)类:经过接口或抽象类声明真实主题和代理对象实现的业务方法。
  2. 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所表明的真实对象,是最终要引用的对象。
  3. 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它能够访问、控制或扩展真实主题的功能。

 

class Subject(object):
    '''
    抽象主题
    '''
    def request(self):
        pass

class RealSubject(Subject):
    def request(self):
        print("访问真实主题类")

class Proxy(Subject):
    __real_subject = None
    def request(self):
        if self.__real_subject is None:
            self.__real_subject = RealSubject()
            self.pre_request()
            self.__real_subject.request()
            self.aft_request()


    def pre_request(self):
        print("访问真实主题以前的预处理。")

    def aft_request(self):
        print("访问真实主题以后的后续处理。")

if __name__ == '__main__':
    p = Proxy()
    p.request()
访问真实主题以前的预处理。
访问真实主题类
访问真实主题以后的后续处理。

应用实例

【例1】韶关“天街e角”公司是一家婺源特产公司的代理公司,用代理模式实现。设计

分析:本实例中的“婺源特产公司”经营许多婺源特产,它是真实主题,提供了显示特产的 display() 方法。而韶关“天街e角”公司是婺源特产公司特产的代理,经过调用婺源特产公司的 display() 方法显示代理产品,固然它能够增长一些额外的处理,如包裝或加价等。客户可经过“天街e角”代理公司间接访问“婺源特产公司”的产品,图所示是公司的结构图。代理

class Specially(object):
    def display(self):
        pass

class RealSpecially(Specially):
    def display(self):
        print("“婺源特产公司”经营许多婺源特产")

class SgProxy(Specially):
    __real_specially = None
    def display(self):
        if self.__real_specially is None:
            self.__real_specially = RealSpecially()
            self.pre_opt()
            self.__real_specially.display()
            self.post_opt()

    def pre_opt(self):
        print("代理商打包")

    def post_opt(self):
        print("代理商发货")

if __name__ == '__main__':
    sp = SgProxy()
    sp.display()
代理商打包
“婺源特产公司”经营许多婺源特产
代理商发货

应用场景

前面分析了代理模式的结构与特色,如今来分析如下的应用场景。

  • 远程代理,这种方式一般是为了隐藏目标对象存在于不一样地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中创建一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
  • 虚拟代理,这种方式一般用于要建立的目标对象开销很大时。例如,下载一幅很大的图像须要很长时间,因某种计算比较复杂而短期没法完成,这时能够先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感受。
  • 安全代理,这种方式一般用于控制不一样种类客户对真实对象的访问权限。
  • 智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增长计算真实对象的引用次数的功能,这样当该对象没有被引用时,就能够自动释放它。
  • 延迟加载,指为了提升系统的性能,延迟对目标的加载。例如,Hibernate 中就存在属性的延迟加载和关联表的延时加载。

模式的扩展

在前面介绍的代理模式中,代理类中包含了对真实主题的引用,这种方式存在两个缺点。

  1. 真实主题与代理主题一一对应,增长真实主题也要增长代理。
  2. 设计代理之前真实主题必须事先存在,不太灵活。采用动态代理模式能够解决以上问题,如 SpringAOP,其结构图如图所示。

相关文章
相关标签/搜索