1.简介
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用
2.静态代理
2.1 概念
静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件。需要代理对象和目标对象实现一样的接口。
- 优点:可以在不修改目标对象的前提下扩展目标对象的功能。
- 缺点:冗余。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。
2.2案例
public interface ITask {
void dispatchTask();
}
/**
* 老板
*/
public class Boss implements ITask {
private static final String TAG = "Boss";
@Override
public void dispatchTask() {
Log.d(TAG, "dispatchTask: ");
}
}
/**
* 秘书
*/
public class Secretary implements ITask {
Boss realObj;
public Secretary( Boss realObj) {
this.realObj = realObj;
}
@Override
public void dispatchTask() {
}
}
调用
Boss boss = new Boss();
final Secretary proxyObj = new Secretary(boss);
proxyObj.dispatchTask();
3.动态代理
动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。
JDK提供了代理对象:
- java.lang.reflect Proxy,主要方法为
static Object newProxyInstance(
ClassLoader loader, //指定当前目标对象的类加载器
Class<?>[] interfaces, //目标对象实现的接口的类型
InvocationHandler h //事件处理器
)
//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
- java.lang.reflect InvocationHandler,主要方法为
Object invoke(Object proxy, Method method, Object[] args)
// 在代理实例上处理方法调用并返回结果。
3.1 案例
public interface IUserDao {
void save();
}
public class UserDao implements IUserDao{
@Override
public void save() {
System.out.println("保存数据");
}
}
public class ProxyFactory {
private Object target;// 维护一个目标对象
public ProxyFactory(Object target) {
this.target = target;
}
// 为目标对象生成代理对象
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务");
// 执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务");
return null;
}
});
}
}
IUserDao target = new UserDao();
System.out.println(target.getClass()); //输出目标对象信息
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
System.out.println(proxy.getClass()); //输出代理对象信息
proxy.save(); //执行代理方法