java代理模式

java代理模式

首先看一张类图,感觉这幅图的描述是比较准确的。subject是一个接口,底下代理类和被代理类实现了这个接口,而被代理类和代理类是关联关系(我理解为代理类包含了一个被代理类的实体)。

代理模式感觉就是把被代理类的装进代理类中,重写被代理类的方法,由于他们共同都实现了一个接口,在代理类中调用方法,实际上就是访问重新封装的方法了。这样做的好处是,一个代理类可以服务多个不同的类,重新封装他们的方法,当然这些类都必须实现同一个接口。

下面的例子我们使用顾客-点餐例子来讲述代理模式。

在点餐的时候,无论是商人、学生、小朋友都要通过服务员来点餐,此时服务员可以当成是一个代理。而不同种类的顾客可以当成是被代理的人。

代码如下:

Customer.java

package reflection.normalproxy;

public interface Customer {
    public void orderDish();
}

WaiterProxy.java

package reflection.normalproxy;

public class WaiterProxy implements Customer {

    Customer customer;
    public WaiterProxy(Customer customer){
        this.customer=customer;
    }
    @Override
    public void orderDish() {
        // TODO Auto-generated method stub
        System.out.println("order before");
        customer.orderDish();
        System.out.println("order after");
        
    }

}

 CustomerImpl.java

package reflection.normalproxy;

public class CustomerImpl implements Customer {

    @Override
    public void orderDish() {
        // TODO Auto-generated method stub
        System.out.println("custom order");
        
    }
    public static void main(String args[]){
        Customer c=new CustomerImpl();
        Customer p=new WaiterProxy(c);
        p.orderDish();
    }
}

 我们把主函数写在了最后一个类里面

输出:

order before
custom order
order after

上面的例子有不方便的地方,就是代理类必须实现某个接口,于是我们可以使用java反射机制的代理类。

Customer.java 还是一样

package reflection.normalproxy;

public interface Customer {
    public void orderDish();
}

WaiterHandler.java

package reflection.proxyclass;

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

public class WaiterHandler implements InvocationHandler {

    Object customer;
    public WaiterHandler(Object customer){
        this.customer=customer;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("order before");
        Object result=method.invoke(customer, args);
        System.out.println("order after");
        
        return result;
    }
}

这个类要实现InvocationHandler接口,跟之前的WaiterProxy类类似,里面提供一个代理方法,只不过这个代理方法是有后面的代理类调用的。

构造函数里面传入被代理的类customer,它可以是非基础类型的Object。

method.invoke()的参数制定了需要代理的类也就是customer以及调用方法时候的参数args,返回值result对应调用代理类调用这个方法的返回结果。由于这个类没有实现接口,有一个问题,那么怎么知道它要调用什么方法呢?如下。

CustomImpl.java

package reflection.proxyclass;

import java.lang.reflect.Proxy;

public class CustomerImpl implements Customer {

    @Override
    public void orderDish() {
        // TODO Auto-generated method stub
        System.out.println("custom order");
        
    }
    public static void main(String args[]){
        CustomerImpl c=new CustomerImpl();
        WaiterHandler h=new WaiterHandler(c);
        
        Customer ci=(Customer)Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), h);
        ci.orderDish();
    }
}
我们把需要代理的类以及handler传入Proxy.newProxyInstance(),这样利用java反射机制,Proxy会获得需要调用的接口的方法。在我们调用这些接口方法的时候,Proxy会调用invoke()方法进行代理。
原文地址:https://www.cnblogs.com/actionscr/p/4866261.html