直接与间接
人们对于复杂的软件系统常常有一种处理手法,即增加一层间接层,从而对系统获得一种更为灵活、满足特定需求的解决方案。
动机(Motivation)
在面向对象系统中,有些对象由于某种原因(比如对想创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等,直接访问会给使用者、或者系统结构带来很多麻烦。
如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。
结构(Structure)
普通代理和强制代理
普通代理:它的要求是客户端只能访问代理角色,不能访问真实角色
强制代理:必须通过真实角色查找到代理角色,也就是说由真实角色管理代理角色。
Proxy模式的几个要点
-
“增加一层间接层”是软件系统中许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。
-
具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy。
-
proxy并不一定要求保持接口的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。
静态代理类似于装饰者模式。
动态代理
面向横切面编程,也就是AOP,其核心就是采用了动态代理机制。
结构:
动态代理实现代理的职责,业务逻辑Subject实现相关的逻辑功能,两者之间没有必然的相互耦合的关系。
示例代码(动态代理):
抽象主题:
public interface Subject{
public void doSomething(String str);
}
真实主题:
public class RealSubject implements Subject{
public void doSomething(String str){
System.out.println("do something!"+str);
}
}
动态代理的Handler类:
public class MyInvocationHandler implements InvocationHandler{
//被代理的对象
private Object target = null;
//通过构造函数传递一个对象
public MyInvocationHandler(Object obj){
this.target = obj;
}
/代理方法
public Object invoke(Object proxy ,Method method,Object[] objs) thows Throwable{
//执行被代理的方法
return method.invoke(this.target,objs);
}
}
动态代理类:
public class DynamicProxy<T>{
public static <T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHanler h){
//寻找JoinPoint连接点,AOP框架使用元数据定义
if(true){
//执行一个前置通知
(new BeforeAdvice()).exec();
}
}
//执行目标,并返回结果
return (T)Proxy.newProxyInstance(loader,interfaces,h);
}
具体业务的动态代理:
public class SubjectDynamicProxy extends DynamicProxy{
public static <T> newProxyInstance(Subject subject){
//获得ClassLoader
ClassLoader loader = subject.getClass().getClassLoader();
//获得接口数组
Class<?>[] classes = subject.getClass().getInterfaces(;
//获得handler
InvocationHandler handler = new MyInvocationHandler(subject);
return newProxyInstance(loader,classes,handler);
}
}
场景类:
public class Client{
public static void main(Stirng[] args){
//定义一个主题
Subject subject = new RealSubject();
//定义主题的代理
Subject proxy = SubjectDynamicProxy.newProxyInstance(subject);
//代理的行为
proxy.doSomething("Finish");
}
}