用反射机制得到动态代理类的构造函数 .
* d. 以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象
*/
public static void main(String[] args) {
ISubject proxy = DynamicProxyFactory.getInstance();
proxy.operator();
System.out.println("proxy class:"+proxy.getClass().getName());
}
}
/**
* 代理接口,要代理业务的抽象
*/
interface ISubject{
public void operator();
}
/**
* 委托类,真正的业务处理
*/
class RealSubject implements ISubject{
@Override
public void operator() {
System.out.println("do something....");
}
}
/**
* 动态代理类对应的调用处理程序类
*/
class SubjectInvocationHandler implements InvocationHandler {
// 代理类持有一个委托类的对象引用
private Object delegate;
public SubjectInvocationHandler(Object delegate) {
this.delegate = delegate;
}
/**
* 利用反射机制将请求分派给委托类处理。 Method的invoke返回Object对象作为方法执行结果(此处没有处理)。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before operator.....");
method.invoke(delegate, args);
System.out.println("after operator....");
return null;
}
}
/**
* 生成动态代理对象的工厂.
*/
class DynamicProxyFactory {
/**
* 客户类可以通过调用此工厂方法获得代理对象.
* 对客户类来说,其并不知道返回的是代理类对象还是委托类对象。
*/
public static ISubject getInstance() {
ISubject delegate = new RealSubject();
InvocationHandler handler = new SubjectInvocationHandler(delegate);
ISubject proxy = null;
proxy = (ISubject) Proxy
.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(), handler);
return proxy;
}
}
运行结果:
before operator.....
do something....
after operator....
proxy class:study.patterns.proxy.$Proxy0
注:静态代理,如果接口增加或删除一个方法,该接口的所有实现类和代理类都需要改变,灵活性和扩展性低。
动态代理,由于动态代理是在运行时动态生成的,所以对接口的改变可以很好的适应。这主要得力于动态代理将接口中声明的所有方法都转移到一个集中的方法中处理,而不是像静态代理那样对接口的每一个方法进行中转。缺点是只能代理接口,且代理类需要实现特定接口(invocationHandler接口),覆盖其invoke方法。
五、模式优缺点
优点:
1、远程代理可以隐藏一个对象存在于不同地址空间的事实,对客户端透明,降低客户端操作的复杂性。
2、 虚拟代理可以根据需要进行最优化,例如延迟对象创建。
3、缓冲代理通过缓存和共享操作执行结果,缩短执行时间,优化系统性能。
4、保护代理和智能指针都可以在访问对象时添加附加的业务逻辑,比如权限判断,引用计数。
5、总体来说,代理模式在访问对象时引入一定程度的间接性,这种间接性很好的起到隔离作用,降低系统的耦合度。
缺点:
1、 实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理。