意图
给某个对象提供一个代理对象,并由代理对象控制对原对象的访问。
类图与角色
主题接口(Subject):具体主题必须实现的接口;
具体主题(Real Subject):对主题接口的实现,代表需要被代理的对象;
代理角色(Proxy):代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。此外,代理对象可以在执行真实对象操作时,附加其他的操作。
实例
静态代理
//主题接口
interface Subject{
public void request();
}
//真实主题
class RealSubject implements Subject{
@Override
public void request(){
System.out.println("处理请求");
}
}
//代理
class ProxySubject implements Subject{
private RealSubject realSubject;
public ProxySubject(RealSubject realSubject){
this.realSubject=realSubject;
}
@Override
public void request(){
preRequest();
realSubject.request();
postRequest();
}
public void preRequest(){
System.out.println("预处理请求");
}
public void postRequest(){
System.out.println("后处理请求");
}
}
//客户端代码
class test {
public static void main (String[] args) throws java.lang.Exception{
ProxySubject proxy=new ProxySubject(new RealSubject());
proxy.request();
}
}
动态代理
//主题接口
interface Subject{
public void request();
}
//真实主题
class RealSubject implements Subject{
@Override
public void request(){
System.out.println("处理请求");
}
}
//动态代理处理器
class ProxyHandler implements InvocationHandler {
Object proxied;
public ProxyHandler( Object proxied ) {
this.proxied = proxied;
}
public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable {
System.out.println("代理对象:"+proxy.getClass().getName());
System.out.println("代理方法:"+method.getName());
System.out.println("预处理请求");
Object obj=method.invoke(proxied, args);
System.out.println("预处理请求");
return obj;
}
}
//客户端代码
class test {
public static void main (String[] args) throws java.lang.Exception{
RealSubject real = new RealSubject();
Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class},
new ProxyHandler(real));
proxySubject.request();
}
}
代理模式与适配器模式
适配器模式的用意是要改变所考虑的对象的接口,而代理模式并不能改变所代理的对象的接口。
代理模式与装饰模式
装饰模式和代理模式都没有改变对象的接口,因此这来种模式很容器混淆。但是,装饰模式应当为所装饰的对象提供增强功能;
代理模式对对象的使用施加控制流(事务控制),并不能提供对象本身的增强功能。
代理模式与外观模式(门面模式)
有时候,外观模式兼任代理的责任,因此在此种情况下可以称为门面代理模式。
其他的代理模式
远程代理
优点是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。
虚拟代理
代理对象可以在必要的时候才将被代理的对象加载。代理可以对加载的过程进行优化或者延迟加载过程,当一个模块的加载十分耗费资源的时候,虚拟代理的优点就非常明显。例如Hibernate的延迟加载功能。
保护代理
可以在运行时对用户的有关权限进行检查,然后在核实后再决定将调用传递给被代理的对象。