1. 定义
代理模式:为其他对象提供一种代理以控制对这个对象的访问。
代理模式也叫做委托模式,它是一项基本设计技巧。许多其他的模式(如状态模式、策略模式、访问者模式)本质上是在更特殊的场合采用了委托模式,而且在日常的应用中,代理模式可以提供非常好的访问控制。
静态代理通用UML:
动态代理通用UML:
2. 使用场景
- 当无法或者不想直接访问某个对象或者访问某个对象存在困难的时候都可以通过代理来访问。
- Android中的IPC机制就使用到了代理模式。
- 面向切面编程(AOP)中,核心就是动态代理。
3. 实现
3.1 普通的静态代理
抽象主题类:
public interface Subject {
void request();
}
具体主题类,也是被代理对象:
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("业务逻辑");
}
}
主题类的代理类:
public class SubjectProxy implements Subject {
private Subject mSubject;
public SubjectProxy(Subject subject) {
mSubject = subject;
}
@Override
public void request() {
//代理中可以增加一些自定义的逻辑,这是面向切面编程的雏形
before();
mSubject.request();
after();
}
public void before() {
System.out.println("before");
}
public void after() {
System.out.println("after");
}
}
场景类:
public class Client {
public static void main(String[] args) {
Subject subject = new SubjectProxy(new RealSubject());
subject.request();
}
}
3.2 动态代理
动态代理的InvocationHandler实现类:
public class SubjectIH implements InvocationHandler {
private Object mTarget;
public SubjectIH(Object target) {
mTarget = target;
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
before();
Object res = method.invoke(this.mTarget, args);
after();
if ("request".equals(method.getName())) {
System.out.println("request!!");
}
return res;
}
public void before() {
System.out.println("before");
}
public void after() {
System.out.println("after");
}
}
场景类:
public class Client {
public static void main(String[] args) {
RealSubject subject = new RealSubject();
//运行的时候动态产生一个代理对象,在实现阶段不用关心代理谁
Subject proxy = (Subject) Proxy.newProxyInstance(
subject.getClass().getClassLoader(),
new Class[]{Subject.class},
new SubjectIH(subject));
proxy.request();
}
}
4. 优点
- 代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了保护目标对象的作用。
5. 缺点
- 由于在客户端和真实对象之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢;
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。