头图

设计模式之代理设计模式

原文首发于微信公众号:jzman-blog,欢迎关注交流!

今天来看一下什么是代理设计模式,顾名思义,代理就是通过中介代替某人做某一件事,对应到我们的程序中就是通过代理对象来控制某个具体对象某个方法的访问,在该方法之前和之后可以做一些额外处理。

  1. 概念理解
  2. 静态代理
  3. 动态代理

概念理解

  • 抽象角色:用于定义真实角色和代理角色共有的方法。
  • 真实角色:真实角色要实现的具体业务逻辑以供代理角色调用。
  • 代理角色:用于代理真实角色,可在真实角色具体逻辑前后进行额外处理。

那么代理的意义在于,当需要具体的业务逻辑时才调用真实角色的具体业务方法,即与真实角色具体业务逻辑无关的处理都放在代理类中的处理。

静态代理

先来看一下静态代理的代码实现,定义抽象角色声明共用的业务逻辑,具体如下:

/**
 * 抽象角色
 * @author jzman
 */
public interface IBusiness {
    /**
     * 购物
     */
    void buy();
}

然后,创建真实角色并完成具体的业务逻辑,具体如下:

/**
 * 真实角色
 * @author jzman
 */
public class RealRole implements IBusiness{
    @Override
    public void buy() {
        System.out.println("我要买东西");
    }
}

然后,创建代理角色,在进行具体业务逻辑的时候必须调用真实角色的业务逻辑方法,具体如下:

/**
 * 代理角色
 * @author jzman
 */
public class ProxyRole implements IBusiness{
    
    private IBusiness mRealRole;
    
    public ProxyRole(IBusiness realRole) {
        this.mRealRole = realRole;
    }

    @Override
    public void buy() {
        //购买之前的额外评估
        System.out.println("购买之前的额外评估...");
        //具体的业务逻辑
        mRealRole.buy();
        //购买之后的满意度调查
        System.out.println("购买之后的满意度调查...");
    }
}

最后,使用刚才创建的相关静态代理类,具体如下:

/**
 * 测试静态代理
 * @author jzman
 */
public class StaticClient {
    public static void main(String[] args) {
        //创建真实角色
        IBusiness realRole = new RealRole();
        //创建代理角色
        IBusiness proxyRole = new ProxyRole(realRole);
        //代购帮你买东西
        proxyRole.buy();
    }
}

测试效果如下:

购买之前的额外评估...
我要买东西
购买之后的满意度调查...

这个案例中,代购不仅帮我们买到了东西,而且在购买行为发生之前和之后做了额外的处理,是不是比较非常灵活呢。

动态代理

上面了解了静态代理,那么动态代理与静态代理有什么区别呢,实际上静态代理和动态代理主要区别是静态代理需要自己生成代理类,而动态代理是在代码运行过程中自动生成代理类,那么动态代理如下实现呢,先来看一看 Java JDK 自带的实现动态代理的关键的两个类或接口,具体如下:

//用于动态生成代理类及其对象
java.lang.reflect.Proxy
//代理角色的调用处理程序需要实现的接口
//用于约束调用者的实现,抽象角色调用方法的时候会被该接口的invoke方法调用
java.lang.reflect.InvocationHandler

下面就来实现一下 Java JDK 自带的动态代理,首先抽象角色和真实角色和上文中静态代理的一样,这里就不在赘述,创建一个代理角色的调用处理程序如下:

/**
 * 代理角色的调用处理程序
 * @author jzman
 */
public class BusinessHandler implements InvocationHandler{

    private IBusiness mRealRole;
    
    public BusinessHandler(IBusiness mRealRole) {
        super();
        this.mRealRole = mRealRole;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //购买之前的额外评估
        System.out.println("购买之前的额外评估...");
        
        //真实角色具体的业务逻辑
        method.invoke(mRealRole, args);
        
        //购买之后的满意度调查
        System.out.println("购买之后的满意度调查...");
        
        return null;
    }
}

使用 Proxy 的静态方法 newProxyInstance() 来生成代理对象,具体如下:

/**
 * 测试JDK自带的动态代理
 * @author jzman
 *
 */
public class DynamicProxyClient {
    public static void main(String[] args) {
        //创建真实角色
        IBusiness mRealRole = new RealRole();
        
        //创建处理器接口
        InvocationHandler handler = new BusinessHandler(mRealRole);
        /**
         * 获取代理角色对应的代理对象
         * newProxyInstance参数(类加载器,自动生成的代理类实现的接口,代理对象的调用处理程序)
         */
        IBusiness proxy = (IBusiness) Proxy.newProxyInstance(handler.getClass().getClassLoader(), mRealRole.getClass().getInterfaces(), handler);
        
        //代理角色帮你买东西
        proxy.buy();
    }
}

上述代码的执行结果如下:

购买之前的额外评估...
我要买东西
购买之后的满意度调查...

学习静态代理有助于对动态代理的学习,两者主要的区别就是动态代理不需要写代理类,其相应的代理类会在代码运行期间动态生成,当然生成的代理类也实现了抽象角色对应的接口,同时创建个代理角色的调用者处理程序(InvocationHandler)也会接管具体的业务逻辑。关于静态代理和动态代理就到此为止。可以选择关注个人微信公众号:躬行之 获取最新更新,一起交流学习!

1.png


躬行之
个人公众号:躬行之(jzmna-blog),推送原创Android技术文章,不限于生活、职场等,不定期更新。
18 声望
5 粉丝
0 条评论
推荐阅读
PHP高级特性-反射Reflection以及Factory工厂设计模式的结合使用[代码实例]
Reflection,即反射。反射提供给面向对象编程可以自省的能力。<br/><br/>这么理解有点太过于概念化,通俗地讲,就是能根据事件的结果反查出原因。在编程中,可以根据一个被实例化的对象,反查出这个...

janrs_com1阅读 1.1k

设计模式大全
设计模式是指在软件设计中经常遇到的一些重复性问题所提供的可复用解决方案,它可以帮助我们提高软件的可维护性、可扩展性和可重用性。Java中的设计模式是基于面向对象编程思想而产生的,它们可以帮助我们更好地...

简相杰1阅读 530

24个写出漂亮代码的小技巧
「Java学习 + 面试指南」: javaguide.cn (一份涵盖大部分 Java 程序员所需要掌握的核心知识)这篇文章我会总结一些实用的有助于提高代码质量的建议,内容较多,建议收藏!内容概览:提取通用处理逻辑注解、反射...

JavaGuide1阅读 453

封面图
Go 语言设计模式之建造者模式
在设计模式中,建造者模式就是解决如何将这些部件组装成一辆完整的汽车并返回给用户的设计模式。建造者模式为客户端返回的不是一个简单的产品,而是一个由多个部件组成的复杂产品。

宇宙之一粟阅读 906

封面图
Go设计模式之装饰器模式
上一步已经实现基础手机的需求,但是手机售卖会有不同的系列,拍照手机广受年轻人的喜爱,所以需要推出一个拍照手机系列,拍照手机具备基础版手机的功能,需要在此基础上新增手机像素的方法,调整基础像素,实现...

liquanhui_99阅读 589

Go设计模式之选项模式
在日常的Go程序开发中,函数(方法)参数的传递是必不可少的一部分,如果参数比较少,可以在方法参数部分直接列出,如果参数很多,可不可以一个一个罗列呢,答案是可以的。但是这种方式存在两个问题:

liquanhui_99阅读 561

手撕代码系列(三)
前言系列首发于公众号『前端进阶圈』 ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。手撕代码系列(三)手写匹配括号 isValid {代码...} 手写大驼峰转下划线 camelCasetoLineCase {代码...} 手...

控心crazy阅读 555

封面图
18 声望
5 粉丝
宣传栏