白话-23种设计模式6-代理模式

举报
object 发表于 2022/07/01 14:53:12 2022/07/01
【摘要】 一、白话  代理模式,指定第三方作为代表。我只负责和我的代表沟通,其他人只能和代理通过,然后代理进行判断是否需要转述给我或者自己处理掉即可。现实举例就像打官司,我们需要请律师来代理我们,我们赋予律师谈判的权利,对方有什么要求也只能跟我律师谈,律师再和我沟通。现实还有很多例子。淘宝店家给工厂代理,代理工厂给品牌方代理加工,火车代售点给火车站代理,自动聊天回复等等。二、定义  代理模式(英语:P...

一、白话

  代理模式,指定第三方作为代表。我只负责和我的代表沟通,其他人只能和代理通过,然后代理进行判断是否需要转述给我或者自己处理掉即可。现实举例就像打官司,我们需要请律师来代理我们,我们赋予律师谈判的权利,对方有什么要求也只能跟我律师谈,律师再和我沟通。现实还有很多例子。淘宝店家给工厂代理,代理工厂给品牌方代理加工,火车代售点给火车站代理,自动聊天回复等等。

二、定义

  代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式。所谓的代理者是指一个类别可以作为其它东西的接口。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

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

三、静态代理

  静态代理:在程序运行之前,代理类的.class文件就已经生成。

/**
 * 抽象角色-提供共有接口
 */
public interface IPerson {
    // 谈判
    public String negotiations(String msg);
}
/**
 * 真实角色-我
 */
public class Me implements IPerson {
    @Override
    public String negotiations(String msg) {
        System.out.println("谈判结束");
        return "谈判结束";
    }
}
/**
 * 代理角色-代替我执行权限
 */
public class Lawyers implements IPerson {

    private IPerson person = new Me(); // 具有真实的角色,赋予权限

    @Override
    public String negotiations(String msg) {
        if ("谈判".equals(msg)) {
            return "谈判中。。。";
        } else if ("接受要求".equals(msg)) {
            System.out.println("中间方:双方互谈");
            return person.negotiations(msg);
        } else {
            return "不同意,继续谈判";
        }
    }
}
public class ProxyApplication {

    // 客户端调用
    public static void main(String[] args) {
        IPerson person = new Lawyers(); // 代理角色
        String result = person.negotiations("接受要求");
        System.out.println("谈判结果 = " + result);
    }
}

输出结果:

MeLawyers的代理关系已确定,查看字节码文件也是存在.class,此时Lawyers只能代理Me

四、动态代理

  JDK动态代理

   JDK动态代理,基于接口实现代理,jdk自带的代理方案,基于反射的机制生成代理对象。方案:需要实现InvocationHandler,通过Proxy生成代理对象。需要注意的是基于接口进行代理,否则会出现转换错误。

/**
 * jdk动态代理,实现InvocationHandler接口
 */
public class JdkProxy implements InvocationHandler {

    private Object target; // 需要代理的目标对象

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK代理开始");
        Object result = method.invoke(target, args);
        System.out.println("JDK代理结束");
        return result;
    }

    // 注入真实对象,生成返回代理对象
    public Object getJDKProxy(Object targetObject) {
        // 为目标对象target赋值
        this.target = targetObject;
        // JDK动态代理,生成代理对象
        Object newProxyInstance = Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(), this);
        return newProxyInstance;
    }

    public static void main(String[] args) {
        JdkProxy jdkProxy = new JdkProxy(); // 实例化JDK动态代理对象
//        Me me = (Me) jdkProxy.getJDKProxy(new Me()); // 获取代理对象
        // JDK需要基于接口进行代理,如果直接使用类,会出现转换错误
        // Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to com.example.proxy.model.Me
        // at com.example.proxy.model2.JdkProxy.main(JdkProxy.java:37)
        IPerson me = (IPerson) jdkProxy.getJDKProxy(new Me()); // 获取代理对象
        me.negotiations("同意接受");// 调用谈判方法
    }
}

    

  Cglib动态代理

     cglib是针对类实现代理,需要额外的依赖包asm和cglib,使用asm字节码框架实现。方案:实现MethodIntercepter接口,通过Enhancer生成真实对象的子类。需要注意,本质是基于生成类的子对象实现,所以不要把类定义成final,否则无用调用

<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>5.0.3</version>
</dependency>

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.1</version>
</dependency>
/**
 * cglib动态代理, 需要单独的依赖,需要实现MethodInterceptor接口
 */
public class CglibProxy implements MethodInterceptor {
    private Object target;

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib 动态代理,代理开始");
        Object result = method.invoke(target, objects);
        System.out.println("cglib 动态代理,代理结束");
        return result;
    }

    public Object getCglibProxy(Object targetObject) {
        this.target = targetObject; // 目标对象赋值
        Enhancer enhancer = new Enhancer();
        // 设置附列,Cglib是针对指定的类生成一个子类
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(this);
        Object result = enhancer.create();// 创建并返回代理对象
        return result;
    }

    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy(); // 实例化CglibProxy对象
        Me meProxy = (Me) cglibProxy.getCglibProxy(new Me()); // 获取代理对象
        meProxy.negotiations("接受请求"); // 代理方法调用
    }

}

五、总结

  优点:一定程度上降低了系统的耦合度。代理模式能将代理对象和真实被调用的目标对象分离。对目标对象的功能增强。有保护对象的作用。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。