代理模式:为其他对象提供一种代理以控制对这个对象的访问。
代理模式 Proxy
代理模式 Proxy[ˈprɑ:ksi] Pattern
:也称为委托模式,控制对象使得只有确实需要这个对象时才创建和初始化。
代理分类
- 静态代理
编译前所有的代码已经存在。
- 动态代理
通过反射机制动态地生成代理对象,也就是代码编译中并不知道代理关系,动态代理将代理和被代理对象进行了解耦。
常见代理功能
- 远程代理
Remote Proxy
常见于 C/S
模式,为某个对象在不同的内存地址空间提供局部代理,使系统可以将 Server
部分实现隐藏,Client
像使用本地对象一样使用 Server
。
- 虚拟代理
Virtural Proxy
使用一个代理对象表示一个十分耗资源的对象,并在真正需要时才创建。
- 保护代理
Protection Proxy
使用代理控制对原始对象的访问,这种模式常见于原始对象有不同的访问权限。
具体实例
- 图片代理
对大图浏览的控制,用户通过浏览器访问网页时先不加载真实的大图,而是通过代理对象的方法来进行处理,在代理对象的方法中,先使用一个线程向客户端浏览器加载一个小图片,然后在后台使用另一个线程来调用大图片的加载方法将大图片加载到客户端。
静态代理
类图结构
结构解析
Subject
抽象类,申明公共接口。
RealSubject
实现类,被代理类或者被委托类,表示真实对象。
Proxy
实现类,代理类或者委托类,它持有真实对象的引用,所有方法中都是对真实对象对应的方法,起到代理作用。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public abstract class Subject { public abstract void operation(); }
public class RealSubject extends Subject{ @Override public void operation() { System.out.println("RealSubject::operation."); } }
public class Proxy extends Subject{ private RealSubject realSubject;
public Proxy() { this.realSubject = new RealSubject(); }
@Override public void operation() { realSubject.operation(); } }
public class TestStaticProxy { public static void main(String[] args) { Proxy proxy = new Proxy(); proxy.operation(); } }
RealSubject::operation.
|
动态代理
基本接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
public class Proxy implements Serializable { public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, InvocationHandler var2) throws IllegalArgumentException {...} }
|
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public interface Subject { void operation(); }
public class RealSubject implements Subject{ public void operation(){ System.out.println("RealSubject::operation."); } }
public class DynamicProxy implements InvocationHandler{ private Object object;
public DynamicProxy(Object object) { this.object = object; }
@Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { Object result = method.invoke(object, objects); return result; } }
public class TestDynamicProxy { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); InvocationHandler dynamicProxy = new DynamicProxy(realSubject);
Subject subject = (Subject) Proxy.newProxyInstance( Subject.class.getClassLoader(), new Class[]{Subject.class}, dynamicProxy); subject.operation(); } }
RealSubject::operation.
|
总结
在代理模式中,要求给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
- 优点
代理模式能够协调调用者和被调用者,降低了系统的耦合度;保护代理可以控制对真实对象的使用权限。
- 缺点
于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
参考文档
- 大话设计模式
Android
源码设计模式解析与实战
- 代理模式