代理模式

简介

Provide a surrogate or placeholder for another object to control access to it.
为其他对象提供一种代理以控制对这个对象的访问。

代理模式(Proxy Pattern) 也称为 委托模式(Delegate),属于 结构型模式 之一。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

通俗的讲,代理模式 就是我们生活中常见的中介。

优缺点

优点

  • 协调调用者和被调用者,降低了系统的耦合度;
  • 代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用;
  • 职责清晰:真实主题角色 只负责实现实际的业务逻辑,无需关心其他非本职责的事务,通过后期代理的访问控制,可以扩展或缩减实际事务,符合设计模式 单一职责原则,代码简洁清晰;
  • 高扩展性:真实主题角色 负责实际业务逻辑,可能经常性变动,但是由于其与 代理类 都实现了 抽象主题,因此,真实主题 的改变不会影响到代理类,符合设计模式 依赖倒置原则里氏替换原则开闭原则
  • 智能化:主要是基于动态代理的实现,可以在程序运行时生成一个合适的代理类;

缺点

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

使用场景

  • 当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过也给代理对象来间接访问;

模式讲解

首先看下 代理模式 的通用 UML 类图:

代理模式

代理模式 一般包含三种角色:

  • 抽象主题角色(Subject)抽象主题类 的主要职责是声明 真实主题代理 的共同接口方法,该类可以是接口也可以是抽象类;
  • 真实主题角色(RealSubject):该类也被称为 被委托类被代理类,该类定义了代理所表示的真实对象,是负责执行系统真正的逻辑业务对象;
  • 代理主题角色(Proxy):也被称为 委托类代理类,其内部持有 RealSubject 的引用,因此具备完全的对 RealSubject 的代理权;

下面是 代理模式 的通用代码展示:

   class Client {

    public static void main(String[] args) {
        ISubject realSubject = new RealSubject();
        ISubject proxy = new Proxy(realSubject);
        proxy.request();
    }

    // 抽象主题 Subject
    public interface ISubject {
        void request();
    }

    // 真实主题 RealSubject
    public static class RealSubject implements ISubject {

        @Override
        public void request() {
            System.out.println("I'm RealSubject.");
        }
    }

    // 代理类 Proxy
    public static class Proxy implements ISubject {
        private ISubject mRealSubject;

        public Proxy(ISubject subject) {
            this.mRealSubject = subject;
        }

        @Override
        public void request() {
            this.doProxy();
            this.mRealSubject.request();
        }

        private void doProxy() {
            System.out.println("代理转发");
        }
    }
}

代理模式的设计中谨记:代理类(Proxy)真实主题(RealSubject) 都要实现 抽象主题(Subject)接口,这样两者的行为才会一致,并且能够允许多重代理的实现。

注意:代理模式 的 UML 类图和通用代码实现上看,代理模式装饰模式 几乎一模一样。代理模式Subject 对应 装饰模式Component代理模式RealSubject 对应 装饰模式ConcreteComponent代理模式Proxy 对应 装饰模式Decorator。确实, 从代码实现上看,代理模式 的确与 装饰模式 是一样的(其实 装饰模式 就是 代理模式 的一个特殊应用),但是这两种设计模式所面向的功能扩展面是不一样的:

  • 装饰模式 强调 自身功能的扩展Decorator 所做的就是增强 ConcreteComponent 的功能(也有可能减弱功能),主体对象为 ConcreteComponent,着重类功能的变化;
  • 代理模式 强调 对代理过程的控制Proxy 完全掌握对 RealSubject 的访问控制,因此,Proxy 可以决定对 RealSubject 进行功能扩展,功能缩减甚至功能散失(不调用 RealSubject 方法),主体对象为 Proxy

简单来讲,假设现在小明想租房,那么势必会有一些事务发生:房源搜索,联系房东谈价格····
假设我们按照 代理模式 进行思考,那么小明只需找到一个房产中介,让他去干房源搜索,联系房东谈价格这些事情,小明只需等待通知然后付点中介费就行了;
而如果采用 装饰模式 进行思考,因为 装饰模式 强调的是 自身功能扩展,也就是说,如果要找房子,小明自身就要增加房源搜索能力扩展,联系房东谈价格能力扩展,通过相应的装饰器,提升自身能力,一个人做满所有的事情。

代理模式 按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。具体内容可查看:Java代理模式

总结:代理模式 应用非常广泛,大到一个系统框架,企业平台,小到代码片段,事务处理,都很有可能用到 代理模式。甚至在其他形式的结构型设计模式中,我们都可以看到 代理模式 的影子,有些模式虽然作为单独的一种设计模式,但倒不如说是 代理模式 的一种针对性优化。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容