Java学设计模式之代理模式

一、代理模式概念

1.1 什么是代理模式

Proxy Pattern,代理模式是指为其他对象提供一种代理,以控制对这个对象的访问,代理对象在客户端,服务端以及目标对象之间起到中介作用。并且是属于一种结构型模式

1.2 代理模式架构示意图

  1. 静态代理模式
    image

  2. 动态代理模式

动态代理没有代理类,可以直接通过反射包下的接口和方法,会通过外部的传参来确定成为哪个类的动态代理对象。并且会通过这个invoke方法来获取目标类对象里面的方法,然后获取到结果之后对这个类进行一个功能的增强。

1.3 代理模式的作用

  1. 功能增强,可以在原有的功能上能可以增加额外的功能
  2. 控制访问,可以通过这个代理类来实现能不能到访问这个目标类

二、静态代理模式代码

2.1 公共接口类

public interface PhoneSell {

    /**
     * 销售方法
     *
     * @param amount 数量
     * @return 价格
     */
    public double sell(Double amount);

}

2.2 目标类

public class XiaoMiFactory implements PhoneSell {

    /**
     * 小米销售方法
     *
     * @param amount 数量
     * @return 价格
     */
    @Override
    public double sell(Double amount) {
        // 小米手机一台卖2000元
        return 2000 * amount;
    }
}

2.3 代理类

public class JingDongShop implements PhoneSell {

    private XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();

    /**
     * 京东商城销售方法
     *
     * @param amount 数量
     * @return 价格
     */
    @Override
    public double sell(Double amount) {
        // 获取小米工厂售价
        double price = xiaoMiFactory.sell(amount);
        // 京东商家也需要赚取一些差价
        price = price + price * 0.1;
        // 返回京东销售小米手机的价格
        return price;
    }
}

2.4 测试类

public class ProxyPatternTest {
    public static void main(String[] args) {
        JingDongShop jingDongShop = new JingDongShop();
        double sell = jingDongShop.sell(1.0);
        System.out.println("手机售价:" + sell);
        // 输出 手机售价:2200.0
    }
}

三、动态代理模式代码

3.1 公共接口类

public interface PhoneSell {

    /**
     * 销售方法
     *
     * @param amount 数量
     * @return 价格
     */
    public double sell(Double amount);

}

3.2 目标类

public class XiaoMiFactory implements PhoneSell {

    /**
     * 小米销售方法
     *
     * @param amount 数量
     * @return 价格
     */
    @Override
    public double sell(Double amount) {
        // 小米手机一台卖2000元
        return 2000 * amount;
    }
}

3.3 动态代理类

public class ProxyInvocationHandler implements InvocationHandler {

    public Object target;

    public ProxyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object;
        //目标方法执行
        //第一个是目标对象,第二个是目标参数
        //这个目标对象是一个动态的,因此需要外面传入
        object = method.invoke(target, args);
        //在获取到这个目标方法之后,可以对这个目标方法进行一个增强功能
        if (object != null) {
            //外部传入这个sell的这个方法,那么执行这个方法的返回值类型为Double
            Double price = (Double) object;
            //手机店获取利润,功能增强
            price = price + price * 0.1;
            object = price;
        }
        return object;
    }
}

3.4 测试类

public class ProxyPatternTest {
    public static void main(String[] args) {
        //1,创建目标对象
        XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();
        //2,创建proxyInvocationHandler对象
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(xiaoMiFactory);
        //3,创建动态代理对象
        //获取目标类类加载器
        ClassLoader classLoader = xiaoMiFactory.getClass().getClassLoader();
        //获取类对应的接口
        Class<?>[] interfaces = xiaoMiFactory.getClass().getInterfaces();
        //通过反射的形式获取代理类
        //强行转换成对应的接口
        PhoneSell proxy = (PhoneSell) Proxy.newProxyInstance(classLoader, interfaces, proxyInvocationHandler);
        //购买数量
        Double sellPrice = proxy.sell(1.0);
        System.out.println("手机售价:" + sellPrice);
        // 输出 手机售价:2200.0
    }
}

四、总结

代理模式主要分为静态代理和动态代理。

静态代理中主要有一个目标类和一个代理类,其两个类都要实现一个共同的接口,做一样的事情,代理对象主要负责转发和功能增强,其具体做事情的还是这个目标对象。静态代理不足的地方在于一个代理类只能绑定一个目标类,如果一个目标类或者多个目标类需要多个代理对象,那么就需要创建大量的代理对象,并且如果接口类里面有一点点的功能的改动,那么这个目标类和代理类就会有大量的改动。

动态代理解决了这个静态代理的问题,在要创建很多代理对象方面,通过一个动态代理对象实现。动态代理主要有jdk的动态代理和cglib的动态代理,jdk动态代理是java里面自带的库,而cglib使用的是第三方库。jdk动态代理主要是通过这个InvocationHandler接口来获取这个目标类和实现代理类的功能增强,并通过反射的方式,获取到这个代理类对象,最后通过这个代理对象获取到对应的方法。

参考资料

posted @ 2024-05-08 17:38  Kllin  阅读(15)  评论(0编辑  收藏  举报