代理模式 ~ 设计模式之七

2022-01-17  本文已影响0人  喏喏2021

1. 什么是代理

我们不直接访问目标对象,而是访问第三方对象,通过这个对象完成目标对象的功能,类似现实中的房屋中介的作用

2. 为什么要用代理

我们就拿房屋中介的例子来讲

  1. 保护了房东的隐私
    一般我们不需要直接和房东联系,对于房东来讲,最后成功交易的就只有一个,其他的,对他来说都是骚扰,呵呵。
  2. 交流便利性
    中介是专业做这个的,对房屋信息,周边环境,人员支持上都会方便一点,而且可能非常热情
  3. 额外服务
    比如一些和银行贷款,房产交易中心的一些信息同步、沟通等,相关手续的办理等,效率也非常地高

3. 具体实现

代理一般我们分为静态代理和动态代理
静态代理:就是在程序运行之前,代理类.class文件就已经存在
动态代理:就是使用反射机制,程序运行中动态生成的

  1. 静态代理实现
public class StaticProxyTest {
    //售卖房屋抽象
    static interface House {
        void sale();
    }
    //被代理对象
    static class HouseOwner implements House {
        @Override
        public void sale() {
            // TODO Auto-generated method stub
            System.out.println("房东售房");
        }
    }
    //代理对象
    static class HouseAgent implements House {
        //存放代理对象
        private HouseOwner owner;
        public HouseAgent(HouseOwner owner) {
            this.owner = owner;
        }
        
        @Override
        public void sale() {
            System.out.println("中介代理售房开始");
            //中间使用代理对象的实际业务
            owner.sale();
            System.out.println("中介代理售房结束");
        }
    }
    public static void main(String[] args) {
        //生成中介代理,需要传进一个房东
        HouseAgent agent = new HouseAgent(new HouseOwner());
        //增强的售卖功能
        agent.sale();
    }
}
//中介代理售房开始
//房东售房
//中介代理售房结束

静态代理总结:

  1. 动态代理实现
    动态代理基本有两种:JDK自带的动态代理和Cglib动态代理。
    1)JDK自带的动态代理
public class DynamicProxyTest1 {
    // 售卖房屋抽象
    static interface House {
        void sale();
    }

    // 被代理对象
    static class HouseOwner implements House {
        @Override
        public void sale() {
            // TODO Auto-generated method stub
            System.out.println("房东售房");
        }
    }
    // 动态代理
    static class HouseDynamicProxy implements InvocationHandler {
        private Object obj;
        
        public HouseDynamicProxy(final Object obj) {
            this.obj = obj;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("中介代理售房开始");
            Object result = method.invoke(obj, args);
            System.out.println("中介代理售房结束");
            return result;
        }
    }
    
    public static void main(String[] args) {
        House house = new HouseOwner();
        //生成动态代理对象
        House houseProxy = (House)Proxy.newProxyInstance(House.class.getClassLoader(), new Class[] {House.class}, 
                new HouseDynamicProxy(house));
        //执行代理方法
        houseProxy.sale();
    }
}
//中介代理售房开始
//房东售房
//中介代理售房结束

2)Cglib代理
JDK自带的代理,需要被代理类实现相关的接口,而如果没有实现接口,该怎么办呢,Cglib就派上用场了。
我们先来看它的实现方法:

public class CglibDynamicProxyTest {
    // 售卖房屋抽象
    static interface House {
        void sale();
    }

    // 被代理对象
    static class HouseOwner implements House {
        @Override
        public void sale() {
            System.out.println("房东售房");
        }
    }

    static class HouseCglibProxy implements MethodInterceptor {

        private Object target;
        
        HouseCglibProxy(final Object target){
            this.target = target;
        }
        
        public Object getInstance(final Object target) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("中介代理售房开始");
            Object result = method.invoke(target, args);
            System.out.println("中介代理售房结束");
            return result;
        }
    }

    public static void main(String[] args) {
        House house = new HouseOwner();
        HouseCglibProxy cglibProxy = new HouseCglibProxy(house);
        HouseOwner houseOwner = (HouseOwner)cglibProxy.getInstance(house);
        houseOwner.sale();
    }
}
//中介代理售房开始
//房东售房
//中介代理售房结束
  1. JDK动态代理实现代理对象的接口,而Cglib是继承了代理对象
  2. 他们都是运行期间生成字节码,但Cglib更复杂一些,因此在生成大量对象时,效率要低一点
  3. Cglib是通过FastClass机制调用,执行效率要比JDk自带的要高一些
    具体用哪个代理,相信大家都有自己的选择了! -_-
上一篇下一篇

猜你喜欢

热点阅读