设计模式之静态代理、动态代理

静态代理

设计模式之静态代理、动态代理_第1张图片

静态代理的好处:

  • 可以使目标对象的业务更加纯粹,不用去关注公共的业务。
  • 在后续需要增加公共业务时,可以在代理对象中增加,而不对目标类进行修改。在项目中要尽量避免对原代码的修改,以免修改原代码后产生严重bug。

缺点:

  • 一个目标类就会产生一个代理类,代码量会提高。

下面直接看代码,房客租房需要找中介,中介再找房东的例子。

租房行为接口:

//租房
public interface Rent {
    void rent();
}

房东实现类 :

//房东
public class MasterHouse implements Rent {
    public MasterHouse() {
    }

    @Override
    public void rent() {
        System.out.println("出租房屋....");
    }
}

中介实现类:

//代理中介
public class MyProxy implements Rent{
    private MasterHouse masterHouse;

    public MyProxy() {
    }

    public MyProxy(MasterHouse masterHouse) {
        this.masterHouse = masterHouse;
    }

    @Override
    public void rent() {
        masterHouse.rent();//中介联系房东租房
    }
}

租客类:

//租客
public class Tenants {
    public static void main(String[] args) {

        MasterHouse masterHouse = new MasterHouse();
        //租客找中介租房
        MyProxy proxy = new MyProxy(masterHouse);
        proxy.rent();
    }
}

通过这样一个中间对象来调用目标对象是比较繁琐,为什么不直接调用目标对象呢?这是为了降低耦合度,也是为了以后如果对目标类有新的公共功能增加时,可以不用修改目标类,直接在代理类中实现。当项目十分庞大时,如果对原代码修改会有很大几率产生问题。 

动态代理

动态代理相比于静态代理在于其对象是动态生成,不用再一个目标类对应一个代理类了,减少了代码量,使代码复用。我们需要某一个目标类的代理对象,只需要将目标对象交给动态生成代理类,让它来生成代理对象。

动态代理分为两大类:

  1. 基于接口:JDK提供的动态代理
  2. 基于类:cglib类

基于接口实现

需要知道

Proxy类:用来动态生成代理对象;

InvocationHandler接口:当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。按照上面的例子通俗来讲就是:租客找中介中介调用rent()方法租房,rent()方法将交给invoke()去自动执行,在中介类中就不需要显示的去调用rent()方法。(这一切的实现都得益于反射机制实现)

设计模式之静态代理、动态代理_第2张图片

 

 动态生成代理对象类(由上面的静态代理类变为动态,将中介类替换成此类):

public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的对象
    private Object target;

    public void setTarget(Object target){
        this.target = target;
    }

    /**生成代理对象
     *      1.调用reflect包下的Proxy类
     *      2.调用Proxy类的newProxyInstance()静态方法生成代理对象
     */
    public Object getProxy(){
        return Proxy.newProxyInstance(
                this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),//获取被代理对象实现的所有的接口
                this
        );
    }

    /**调用目标对象的方法
     * @param proxy  代理对象
     * @param method  被代理对象的方法
     * @param args  被代理对象 方法被调用时 传入的实参
     * @return
     * @throws Throwable
     */

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target, args);//调用目标对象的方法
        return result;
    }
}

租客类: 

public class Tenants {
    public static void main(String[] args) {

        MasterHouse masterHouse = new MasterHouse();//房东

        /**
         * 生成代理对象
         * 相当于上面的MyProxy proxy = new MyProxy(masterHouse);
         */
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(masterHouse);//设置要代理的目标类对象
        Rent proxy = (Rent) pih.getProxy();//获取代理对象
        
        //租房
        proxy.rent();
    }
}

你可能感兴趣的:(java,设计模式,代理模式)