资讯专栏INFORMATION COLUMN

设计模式|代理模式

QiShare / 1774人阅读

摘要:三二模式分析代理模式的示意图结构比较简单一般可以简化如下图所示。五总结在代理模式中,要求给某一个对象提供一个代理,并由代理对象控制对原对象的访问,其英文为是一种结构型模式。

一、写在前面

代理模式是常用的结构型设计模式之一、当我们直接访问某些对象存在问题时可以通过代理模式来间接访问,为了保证客户端使用的透明性、所访问的真实对象和代理对象都必须实现同一个接口。

二、代理模式动机与定义

某人要找对象(大部分是程序员),但是由于某些原因(996)不能直接去找。

于是就委托一个中介机构去帮自己完成找女朋友的过程,如婚姻中介所、某某社交软件等。

在这里婚姻介绍所或者某某社交软件就是一个代理,帮你找美女。

在我们生活中代理无处不在、比如房屋中介、职业中介(某某招聘网)等它们充当的都是一个代理角色。

所谓的代理就是一个人或者一个机构代表另一个人或者机构采取行动。

二.一 模式动机

在某些情况下,一个客户不想或者不能直接应用另一个对象,可以通过一个称之为‘代理’的第三者来实现间接的引用。

代理对象在客户和目标对象之间起到一个中介的作用,并且可以通过代理对象去掉某些客户不能看到的内容或者服务,同时也可以添加客户需要的额外服务。

二.二 模式的定义

代理模式(Proxy Patten)定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

代理对象英文名称叫做 Peoxy 或者 Surrogate 他是一种对象结构模式。

三、代理模式结构与分析

代理模式结构比较简单、其核心就是一个代理类,下面我们来分析下其模式结构

三.一 模式结构

代理模式UML图

代理模式包含以下三个角色

Subject(抽象主题角色)
抽象主题角色申明了真实主题和代理主题的共同接口、这样以来任何使用真实主题的地方可以都使用代理主题、客户端需要针对抽象主题角色来编程

Proxy(代理主题角色)
代理主题角色包含了对真实主题的引用,从而可以在任何时候操作真实主题角色。

RealSubject(真实主题角色)
真实主题角色定义了代理主题角色所代表的具体对象,真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色来间接的调用真实主题角色中定义的方法。

三.二模式分析

代理模式的示意图结构比较简单、一般可以简化如下图所示。
但是在现实中要复杂的多。

典型的代理类代码如下:

public class Proxy implements Subject {

    private RealSubject realSubject = new RealSubject();

    public void preRequest() {
        System.out.println("---pre---");
    }

    public void request() {
        preRequest();

        realSubject.request();

        postRequest();

    }

    public void postRequest() {
        System.out.println("----post-----");
    }

}

在真实应用中,代理类的实现好比着复杂的多,它需要一套自己的方式去访问真实对象,以便作为真实对象的代理。

四、代理模式的实例

代理模式在我应用开发中一般就分为静态代理和动态代理两类。
下面我们来一个例子来具体的理解下代理模式

四.一 静态代理

下面我们以我们最熟悉的Spring AOP 处理事务的方式来实现,废话不多说直接上代码吧!

抽象角色

public interface TrancationSubject {
    
    void request();

}

具体角色

public class TrancationRealSubject implements TrancationSubject {

    public void request() {
        System.err.println("---执行事务方法---");
    }

代理角色

public class TrancationProxy implements TrancationSubject {

    private TrancationRealSubject realSubject;

    public TrancationProxy(TrancationRealSubject realSubject) {
        super();
        this.realSubject = realSubject;
    }

    public void preRequest() {
        System.out.println("---open trancation---");
    }

    public void request() {
        preRequest();

        realSubject.request();

        postRequest();

    }

    public void postRequest() {
        System.out.println("----commit/rollback-----");
    }

}

client端

public class Client {

    public static void main(String[] args) {

        TrancationProxy proxy = new TrancationProxy(new TrancationRealSubject());
        proxy.request();
    }

}

执行结果

---open trancation---
---执行事务方法---

----commit/rollback

上述静态代理其优点就不多说了,继承了代理模式的优点,但是其缺点就不得不唠叨下了。

缺点:
1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。

由于这两种致命的缺点到这在真实的应用环境中很难看到静态代理的使用。

下面我们来说说其高配版。

四.二 动态代理

动态代理是一种高级代理模式,最典型的引用场景就是Spring AOP 。

Java动态到了实现相关包主要位于java.lang.reflect包下面主要涉及两个类

(1) InvocationHandler 接口,它是代理实例的调用处理程序实现的接口,该结构定义了如下方法。

Object invoke(Object proxy,Method method,Object[] args) throws Throwable

在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。

参数:

proxy - 在其上调用方法的代理实例

method - 对应于在代理实例上调用的接口方法的 Method 实例。 Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。

args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。

(2) Proxy 类,该类即为动态代理类,最常用的方法为

newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

参数:

loader - 定义代理类的类加载器

interfaces - 代理类要实现的接口列表

h - 指派方法调用的调用处理程序

对上面动态代理一些主要方法做下了解,下面我们该早上面代理类。

public class DynamicProxy implements InvocationHandler {

    private Object obj;

    public DynamicProxy(Object obj) {
        super();
        this.obj = obj;
    }

    public void preRequest() {
        System.out.println("---open trancation---
");
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        preRequest();

        Object invoke = method.invoke(obj, args);

        postRequest();

        return invoke;
    }

    public void postRequest() {
        System.out.println("----commit/rollback-----");
    }
}

client

public class Client {

    public static void main(String[] args) {

        DynamicProxy invocationHandler = new DynamicProxy(new TrancationRealSubject());

        TrancationSubject newProxyInstance = (TrancationSubject) Proxy.newProxyInstance(
                TrancationSubject.class.getClassLoader(), new Class[] { TrancationSubject.class }, invocationHandler);
        
        newProxyInstance.request();

    }

}

在这执行结果就不贴了。

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。
这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强。

五、总结

在代理模式中,要求给某一个对象提供一个代理,并由代理对象控制对原对象的访问,其英文为proxy 是一种结构型模式。

代理模式包含三种角色,抽象主题角色、代理主题角色、真实主题角色。

代理模式的优点在于协调调用者和被调用者,在一定的程度上降低了系统的耦合性。其缺点在调用者和被调用者中间增加了代理层,因此有些类型的代理模式可能会造成请求处理速度变慢,并且代理模式需要额外的工作,有些代理模式的实现非常复杂。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74864.html

相关文章

  • 我的Java设计模式-代理模式

    摘要:下面总结了它俩的异同相同点都需要实现同一个接口或者继承同一个抽象类,并且代理角色和装饰角色都持有被代理角色和构件角色的引用。 写完上一篇之后有小伙伴问我有没有写过代理模式,想看看我的理解。原本我的设计模式系列是按照创建型-行为型-结构型的顺序写下去的,既然小伙伴诚心诚意了,我就大发慈悲的穿插一篇代理模式。开玩笑,题外话。 说起代理模式,就不由得想起经纪人,说起经纪人,就想起了...对,...

    makeFoxPlay 评论0 收藏0
  • 我的Java设计模式-代理模式

    摘要:下面总结了它俩的异同相同点都需要实现同一个接口或者继承同一个抽象类,并且代理角色和装饰角色都持有被代理角色和构件角色的引用。 写完上一篇之后有小伙伴问我有没有写过代理模式,想看看我的理解。原本我的设计模式系列是按照创建型-行为型-结构型的顺序写下去的,既然小伙伴诚心诚意了,我就大发慈悲的穿插一篇代理模式。开玩笑,题外话。 说起代理模式,就不由得想起经纪人,说起经纪人,就想起了...对,...

    BWrong 评论0 收藏0
  • 代理模式和装饰者模式

    摘要:简介代理模式和装饰者模式是两种常见的设计模式。这里通过构造函数的参数将被代理对象传入到代理中,也可以通过其它方式,如提供一个方法。下面是的代码输出首先依然是先创建一个需要被代理的对象,然后把它传入到的构造函数中。 简介 代理模式和装饰者模式是两种常见的设计模式。代理模式是为其它对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以...

    NusterCache 评论0 收藏0
  • js设计模式 --- 代理设计模式

    摘要:代理设计模式代理模式为其他对象提供一种代理以控制对这个对象的访问。代理模式是常见的设计模式之一是指不直接调用实际的对象,而是通过代理对象,来间接的调用实际的对象。对象类定义了代理对象所代表的目标对象。 代理设计模式 代理模式:为其他对象提供一种代理以控制对这个对象的访问。代理模式是常见的设计模式之一,是指不直接调用实际的对象,而是通过代理对象,来间接的调用实际的对象。为什么要采用这种间...

    Tonny 评论0 收藏0
  • 每天一个设计模式·代理模式

    摘要:代理模式原文地址更多设计模式系列教程更多免费教程博主按每天一个设计模式旨在初步领会设计模式的精髓,目前采用靠这吃饭和纯粹喜欢两种语言实现。代理模式优缺点代理模式有高度解耦对象保护易修改等优点。 代理模式·原文地址 更多《设计模式系列教程》 更多免费教程 博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript(_靠这吃饭_)和python(_纯粹喜欢_)...

    XiNGRZ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<