• linkin大话设计模式--代理模式


    代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象的时候,客户端并不关心是否可以准确的得到这个对象,他只要一个能够提供该功能的对象而已,此时我们就可以返回该对象的代理。总而言之,客户端代码不能或者不想直接访问被调用对象,服务器这段额外的建立一个代理对象返回给客户端使用,那么这种设计方式就是代理模式。


    自从JDK的版本到1.3以后,java语言通过java.lang.reflect库中,提供了三个类来直接支持代理模式。分别是:ProxyInvocoationHandlerMethodProxy类使得设计师能够在运行时间创建代理对象,当系统有了一个代理对象后,对源对象的方法调用会首先被分派给一个调用处理器(InvocationHandler//接口,InvocationHandler接口中有一个invoke()方法,程序可以在调用处理器的invoke方法中截获这个调用,进行额外的操作。


    创建动态代理对象的步骤:

    1.指明一系列的接口来创建一个代理对象

    2.创建一个调用处理器(InvocationHandler)对象

    3.将这个代理指定为某个其他对象的代理对象

    4.在调用处理器的invoke方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要做的操作。


    其中代理模式在hibernate和spring中都有应用,下面代码模拟hibernate中的懒加载。

    代码如下:

    <strong><span style="font-size:14px;">//代理和实际对象都要实现的接口
    interface Image{
        //随便定义一个方法
        public void show();
    }
    
    //模拟客户端使用的代理
    class ImageProxy implements Image{
        
        private Image image;
    
        public ImageProxy(Image image) {
            super();
            this.image = image;
        }
    
        @Override
        public void show() {
            //加入自己的代码逻辑 在用到这个show方法的时候  才会去真正的创建那个实实在在的对象
            if(null == image){
                image = new BigImage();
            }
            image.show();
        }
        
    }
    
    //实际的对象
    public class BigImage implements Image{
        
        public BigImage(){
           try {
            Thread.sleep(5000);
            System.out.println("BigImage...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        }
    
        @Override
        public void show() {
            System.out.println("梦似烟花心似水,同学少年不言情。。。");
        }
        
        
        public static void main(String[] args) {
            //直接使用真正的对象 在new那个对象的时候会有的5000秒的延迟
            long stateTime1 = System.currentTimeMillis();
            Image image1 = new BigImage();
            System.out.println(System.currentTimeMillis() - stateTime1+"
    ");
            
            //使用代理,直接很快的创建了一个代理对象,在真正使用到对象的show方法的时候 才会有5000秒的延迟
            long stateTime = System.currentTimeMillis();
            Image image = new ImageProxy(null);
            System.out.println(System.currentTimeMillis() - stateTime);
            image.show();
            
        }
    
    }
    
    </span></strong>



    在spring中也使用了代理模式,其中spring的AOP就是代理模式的一个典型应用。

    <strong><span style="font-size:14px;">import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    //java动态代理  代理对象和被代理对象都要实现的接口 
    interface Dog{
        public void info();
        
        public void run();
    }
    
    //模拟事务管理器
    class TxUtil{
        
        public void beginTx(){
            System.out.println("...模拟事务开始...");
        }
        
        public void endTx(){
            System.out.println("...模拟事务结束...
    ");
        }
    }
    
    //java动态代理的关键之一,InvocationHandler的实现类,这个类的invoke方法将成为最后代理对象方法的实现
    class LinkinInvocationHandler implements InvocationHandler{
        //需要被代理的对象
        private Object target;
        
        public void setTarget(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            TxUtil txUtil = new TxUtil();
            txUtil.beginTx();
            //方法的反射 需要被代理的对象作为主调来调用方法 
            Object result = method.invoke(target, args);
            txUtil.endTx();
            return result;
        }
        
    }
    
    //模拟一个获得代理对象的工厂  
    class LinkinProxyFactory{
        public static Object getProxyInstance(Object target){
            LinkinInvocationHandler hander = new LinkinInvocationHandler();
            hander.setTarget(target);
            //改天复习下反射 注意下面方法的返回值
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), hander);
        }
    }
    
    //被代理对象
    public class MyDog implements Dog{
    
        @Override
        public void info() {
            System.out.println("忠犬8公...");
        }
    
        @Override
        public void run() {
            System.out.println("很忠诚的...");
        }
        
        
        public static void main(String[] args) {
            //获得一个被代理对象
            MyDog myDog = new MyDog();
            //以被代理对象作为参数获得一个代理对象  一般情况下编译类型都是接口
            Dog myDogProxy = (Dog) LinkinProxyFactory.getProxyInstance(myDog);
            myDogProxy.info();
            myDogProxy.run();
        }
    
    }</span></strong>

  • 相关阅读:
    【luogu P1073 最优贸易】 题解
    【luogu P2919 [USACO08NOV]守护农场Guarding the Farm】 题解
    【luogu P3946 ことりのおやつ】 题解
    【luogu P3393 逃离僵尸岛】 题解
    ubuntu问题: 同时只能有一个软件管理工具在运行
    Windows server 2008 r2 开启Aero
    windows8.1安装之后的感想
    20条Linux命令面试问答
    9个常用iptables配置实例
    Linux SSH安全技巧
  • 原文地址:https://www.cnblogs.com/LinkinPark/p/5233190.html
Copyright © 2020-2023  润新知