代理模式

目的

代理模式是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。

解释

代理设计模式

优缺点

优点

  • 职责清晰
  • 高扩展,只要实现了接口,都可以用代理。
  • 智能化,动态代理。

缺点

  • 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
  • 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

示例

应用实例:

  1. Windows 里面的快捷方式。
  2. 猪八戒去找高翠兰结果是孙悟空变的,可以这样理解:把高翠兰的外貌抽象出来,高翠兰本人和孙悟空都实现了这个接口,猪八戒访问高翠兰的时候看不出来这个是孙悟空,所以说孙悟空是高翠兰代理类。
  3. 买火车票不一定在火车站买,也可以去代售点。
  4. 一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。
  5. spring aop。

案例:腾讯视频代理

程序库提供了视频下载类。 但是该类的效率非常低。 如果客户端程序多次请求同一视频, 程序库会反复下载该视频, 而不会将首次下载的文件缓存下来复用。

代理类实现和原下载器相同的接口, 并将所有工作委派给原下载器。 不过, 代理类会保存所有的文件下载记录, 如果程序多次请求同一文件, 它会返回缓存的文件。

// 远程服务接口。
interface ThirdPartyTVLib is
    method listVideos()
    method getVideoInfo(id)
    method downloadVideo(id)
 
// 服务连接器的具体实现。该类的方法可以向腾讯视频请求信息。请求速度取决于
// 用户和腾讯视频的互联网连接情况。如果同时发送大量请求,即使所请求的信息
// 一模一样,程序的速度依然会减慢。
class ThirdPartyTVClass implements ThirdPartyTVLib is
    method listVideos() is
        // 向腾讯视频发送一个 API 请求。
 
    method getVideoInfo(id) is
        // 获取某个视频的元数据。
 
    method downloadVideo(id) is
        // 从腾讯视频下载一个视频文件。
 
// 为了节省网络带宽,我们可以将请求结果缓存下来并保存一段时间。但你可能无
// 法直接将这些代码放入服务类中。比如该类可能是第三方程序库的一部分或其签
// 名是`final(最终)`。因此我们会在一个实现了服务类接口的新代理类中放入
// 缓存代码。当代理类接收到真实请求后,才会将其委派给服务对象。
class CachedTVClass implements ThirdPartyTVLib is
    private field service: ThirdPartyTVLib
    private field listCache, videoCache
    field needReset
 
    constructor CachedTVClass(service: ThirdPartyTVLib) is
        this.service = service
 
    method listVideos() is
        if (listCache == null || needReset)
            listCache = service.listVideos()
        return listCache
 
    method getVideoInfo(id) is
        if (videoCache == null || needReset)
            videoCache = service.getVideoInfo(id)
        return videoCache
 
    method downloadVideo(id) is
        if (!downloadExists(id) || needReset)
            service.downloadVideo(id)
 
// 之前直接与服务对象交互的 GUI 类不需要改变,前提是它仅通过接口与服务对
// 象交互。我们可以安全地传递一个代理对象来代替真实服务对象,因为它们都实
// 现了相同的接口。
class TVManager is
    protected field service: ThirdPartyTVLib
 
    constructor TVManager(service: ThirdPartyTVLib) is
        this.service = service
 
    method renderVideoPage(id) is
        info = service.getVideoInfo(id)
        // 渲染视频页面。
 
    method renderListPanel() is
        list = service.listVideos()
        // 渲染视频缩略图列表。
 
    method reactOnUserInput() is
        renderVideoPage()
        renderListPanel()
 
// 程序可在运行时对代理进行配置。
class Application is
    method init() is
        aTVService = new ThirdPartyTVClass()
        aTVProxy = new CachedTVClass(aTVService)
        manager = new TVManager(aTVProxy)
        manager.reactOnUserInput()

UML 图

代理模式示例的结构