代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。
以下是实现一个用户上网的代理实现:
//定义Network接口
interface Network{
//定义浏览的抽象方法
public void browse();
}
//真实上网操作
class RealCustomer implements Network{
@Override
public void browse() {//覆写抽象方法
System.out.println("上网浏览信息");
}
}
//代理上网
class Proxy implements Network{
private Network network;
//设置代理的真实操作
public Proxy(Network network) {
//设置代理的子类
this.network = network;
}
//与具体上网相关的操作
public void check(){
System.out.println("用户是否合法");
}
@Override
public void browse() {
this.check();//可以调用多个与具体业务相关的操作
this.network.browse();//调用真实上网操作
}
}
public class ProxyGOF {
public static void main(String[] args) {
//定义接口对象
Network network = null;
//实例化代理,同时传入代理的真实操作
network = new Proxy(new RealCustomer());
network.browse();//客户实现上网功能,不关心代理是如何实现的
}
}
这种代理只能实现一个接口的子类对象,无法实现多接口的子类对象。需要使用动态代理来解决这种问题。
想要实现动态代理设计的实现,代理类不再局限于具体实现某一个具体的类。
在Java核心API中提供了一个java.lang.reflect.InvocationHandler
接口。
public interface InvocationHandler {
/**
*处理代理实例上的方法调用并返回结果。 当在与之关联的代理实例上调用方法时,将在调用处理程序中调用此方法。
* @param proxy 调用该方法的实例
* @param method 返回的是被调用的方法对象,取得了Method对象意味着可以使用invoke()反射调用方法
* @param args 表示方法中接收到的参数
* @return 方法的返回值
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
如果要想进行对象的绑定,那么就需要使用到一个Proxy的程序类,这个程序类的主要功能是可以绑定所有的你需要绑定的接口子类的对象,而且这些对象都是根据接口自动创建的,该类中有一个动态创建绑定对象的方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) IllegalArgumentException
动态代理的实现实例:
package com.czl.gof;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface ISubject{//代理设计的核心在于有一个核心接口操作
public void browse(String user,String pass);//用户上网是核心业务
}
class RealSubject implements ISubject{//真实用户实现上网功能
@Override
public void browse(String user, String pass) {
System.out.println("[userName] : " + user + ", [password] :" + pass);
}
}
class DynamicProxy implements InvocationHandler{
private Object target;//绑定任意的接口对象,使用Object类型
/**
* 实现真实对象的绑定处理,同时返回代理对象
* @param target
* @return 返回一个代理对象(这个对象是根据接口定义动态创建形成的代理对象)
*/
public Object bind(Object target) {
this.target = target;
//返回一个代理对象。
//target.getClass().getClassLoader()表示接口对象的类加载路径;
//target.getClass().getInterfaces()表示接口对象数,是一个数组对象;
//this表示当前对象,在次类中指的是DynamicProxy类对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
//定义代理实现的方法
public void register(){
System.out.println("register");
}
public void logout(){
System.out.println("log out");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.register();//调用登记方法
//反射调用实现真实主题的方法
Object ret = method.invoke(this.target, args);
this.logout();//调用登出方法
return ret;
}
}
public class ProxyGOF {
public static void main(String[] args) {
ISubject subject = (ISubject) new DynamicProxy().bind(new RealSubject());
subject.browse("tom", "123");
}
}