代理模式

什么是代理

这里的代理可以联系生活中的代理,就是代表某些人或事物做一些事情,举几个例子:1.中介就是一个典型的代理,你把房子挂到中介,中介就会帮你把房子的标价报给想买房的人;2.你打官司的时候,花钱请了律师,律师就会帮你打官司,替你说话..等等现实中有很多代理的例子。

为什么使用代理

还是引用上面的例子,你之所以把房子挂到中介,是因为你很忙,没时间处理,而且中介可以联系更多的买家;请律师,是因为律师懂得更多的法律知识,相当于对你进行了武装。

软件应用中的代理

经过上面对现实生活中代理的简单介绍,下面说一下我们编写软件应用中代理模式的使用。
在软件应用中,代理模式的使用有三种情况:静态代理,JDK动态代理),cglib动态代理;下面进行分别的介绍。

  • 静态代理
    静态代理是指被代理类和代理类都实现同一个接口,对于被代理类的方法访问需要通过代理类调用
  • 静态代理的缺点:
    1、代理的职能单一,在代码中需要写多个代理来完成不同的功能
    2、在编译器已经确定对被代理类的方法的调用,不适合做更多的扩展

示例代码:
首先是公用接口

/**
 * Created by bitsino-001 on 2019/5/17.
 * 通过房子中介演示静态代理
 * 这是个买房者和中介的公用接口
 */
public interface SellHouse {
    void price_house();
}

被代理类实现公用接口,这里就是卖房子的人

/**
 * Created by bitsino-001 on 2019/5/17.
 * 实际卖方的人(被代理类)
 */
public class Seller implements SellHouse {
    @Override
    public void price_house() {
        System.out.println("我是房主,万科洋房,110平,售价150万!");
    }
}

接下来是代理类也实现公用接口,这里就是房屋中介

/**
 * Created by bitsino-001 on 2019/5/17.
 * 中介代理类
 */
public class Zhongjie implements SellHouse {
    //
    Seller seller = new Seller();

    @Override
    public void price_house() {
        System.out.println("我是房屋中介,房主急售!");
        seller.price_house();
    }
}

下面是测试代码

/**
 * Created by bitsino-001 on 2019/5/17.
 */
public class TestProxy {
    public static void main(String[] args) {
        SellHouse sellHouse = new Zhongjie();
        sellHouse.price_house();
    }
}

输出结果:通过代理类调用了被代理类的方法,同时,也可以看做代理类对被代理类做了宣传,也可以叫做增强,这个概念在后面的学习中会看到,如果学习了spring ,对AOP有了解那么这个概念应该熟悉。


图片.png
  • JDK动态代理
    JDK动态代理和静态代理类似,需要实现公共的接口,但是弥补了上面说的静态代理的缺点。动态代理是在运行时动态的为被代理类创建代理对象,公用接口中的方法都被转移到调用处理器一个集中的方法中执行,可以更加灵活的处理多个方法的调用执行。

示例代码:

package dynamic_proxy;

/**
 * Created by bitsino-001 on 2019/5/17.
 * 一个普通的用户,需要请律师代理他打官司
 */
public class User implements DaGuanSi {
    @Override
    public void juzheng() {
        System.out.println("用户请律师帮忙举证");
    }

    @Override
    public void susong() {
        System.out.println("用户请律师帮忙诉讼");
    }
}
package dynamic_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by bitsino-001 on 2019/5/17.
 * 演示如何实现动态代理
 *
 */
public class TestDynamicProxy {
    public static void main(String[] args) {
        //获得代理类,需要用到JDK中的 Proxy.newProxyInstance()方法
        // 在Proxy.newProxyInstance()中需要传入三个参数
      /*  public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
      *    第一个是被代理类的类加载器,第二个是被代理类实现的接口,第三个参数是用来动态调用方法的接口
      *    想必介绍到这里,熟悉java反射的朋友应该想到了,动态代理是通过反射来实现的运行时方法调用
      * */

        User user = new User();
          //获得代理对象
        DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
            @Override
          //当通过代理对象调用xxx方法时就会调用下面的方法执行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("各位好,我是代理律师");
                Object invoke = method.invoke(user,args);//这里就是通过反射执行代理类的方法,也就是间接的调用被代理类的方法
                System.out.println("本代理律师发言完毕");
                return invoke;
            }
        });

        proxy.juzheng();
        proxy.susong();



    }
}


为了演示动态代理的优势,我们再通过动态代理来为上面的卖房子的例子做一下实现,这次我们只需要将动态代理中的代理对象声名为Seller(卖房者),接口改成卖房子的公共接口,就会动态的生成代理对象,当调用代理对象的方法时,也会调用被代理对象的方法。

package dynamic_proxy;

import static_proxy.SellHouse;
import static_proxy.Seller;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by bitsino-001 on 2019/5/17.
 * 演示如何实现动态代理
 *
 */
public class TestDynamicProxy {
    public static void main(String[] args) {
        //获得代理类,需要用到JDK中的 Proxy.newProxyInstance()方法
        // 在Proxy.newProxyInstance()中需要传入三个参数
      /*  public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
      *    第一个是被代理类的类加载器,第二个是被代理类实现的接口,第三个参数是用来动态调用方法的接口
      *    想必介绍到这里,熟悉java反射的朋友应该想到了,动态代理是通过反射来实现的运行时方法调用
      * */

    /*    User user = new User();
        //获得代理对象
        DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            //当通过代理对象调用xxx方法时就会调用下面的方法执行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("各位好,我是代理律师");
                Object invoke = method.invoke(user,args);//这里就是通过反射执行代理类的方法,也就是间接的调用被代理类的方法
                System.out.println("本代理律师发言完毕");
                return invoke;
            }
        });

        proxy.juzheng();
        proxy.susong();*/


        Seller seller = new Seller();
        //获得代理对象
        SellHouse proxy = (SellHouse) Proxy.newProxyInstance(seller.getClass().getClassLoader(), seller.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            //当通过代理对象调用xxx方法时就会调用下面的方法执行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("各位好,我是代理律师");
                Object invoke = method.invoke(seller,args);//这里就是通过反射执行代理类的方法,也就是间接的调用被代理类的方法
                System.out.println("本代理律师发言完毕");
                return invoke;
            }
        });

       proxy.price_house();



    }
}

你可能感兴趣的:(代理模式)