代理模式
代理就是请别人帮你办事,但是别人只能在你委托的事情上代表你,不会拥有其他权限。代理更多是通过接口限定功能。
1. 使用场景
客户端不想直接访问某对象(保护代理),或直接访问某对象时有困难(远程代理),就可以使用一个代理对象来实现间接访问。真实对象和代理对象必须实现相同的接口,才能让客户端实现透明的访问。
2. 角色
- Subject 抽象主题类,用于声明真实对象和代理对象共同的接口方法。
- RealSubject 真实主题类,被代理的对象,客户端通过代理对象间接访问该对象中方法。
- ProxySubject 代理类,持有真实对象的引用,并实现代理接口。
3. 实践
静态代理:只能给实现了约定的代理接口的类对象做代理。
// 例子1
// 抽象主题
public abstract class Subject {
public abstract void visit();
}
// 真实类
public class RealSubject extends Subject {
@Override
public void visit() {
System.out.println("真实对象: ");
}
}
// 代理类,持有真实对象的引用,间接调用真实对象的方法
public class ProxySubject extends Subject {
private RealSubject mSubject;
public ProxySubject(RealSubject subject) {
mSubject = subject;
}
@Override
public void visit() {
mSubject.visit();
}
}
// 客户端调用
RealSubject real = new RealSubject()
ProxySubject proxy = new ProxySubject(real);
proxy.visit();
// 例子2
// 要代理的接口
public interface ILawsuit {
// 提交申请
void submit();
// 进行举证
void burden();
// 开始辩护
void defend();
// 诉讼完成
void finish();
}
// 被代理的类
public class XiaoMin implements ILawsuit {
@Override
public void submit() {
System.out.println("老板拖欠工资,特此申请仲裁!");
}
@Override
public void burden() {
System.out.println("这是合同书和过去一年的银行流水!");
}
@Override
public void defend() {
System.out.println("证据确凿,不需要再说什么了!");
}
@Override
public void finish() {
System.out.println("诉讼胜利");
}
}
// 代理类
public class Lawyer implements ILawsuit {
private ILawsuit mILawsuit;
public Lawyer(ILawsuit ILawsuit) {
mILawsuit = ILawsuit;
}
@Override
public void submit() {
mILawsuit.submit();
}
@Override
public void burden() {
mILawsuit.burden();
}
@Override
public void defend() {
mILawsuit.defend();
}
@Override
public void finish() {
mILawsuit.finish();
}
}
// 客户端调用
XiaoMin xiaomin = new XiaoMin();
ILawsuit lawyer = new Lawyer(xiaomin);
lawyer.submit();
lawyer.burden();
lawyer.defend();
lawyer.finish();
动态代理:通过反射动态生成代理者对象,在编码阶段代理类无需知道要代理哪些对象,即实现了代理类和被代理类的解耦。
// 创建动态代理类
public class DynamicProxy implements InvocationHandler {
private Object mObject;
public DynamicProxy(Object object) {
mObject = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(mObject, args);
return result;
}
}
// 动态代理调用
System.out.println("**********动态代理**********");
DynamicProxy proxy1 = new DynamicProxy(xiaomin);
ClassLoader loader = xiaomin.getClass().getClassLoader();
ILawsuit lawsuit = (ILawsuit) Proxy.newProxyInstance(loader, new Class[]{ILawsuit.class}, proxy1);
lawsuit.submit();
lawsuit.burden();
lawsuit.defend();
lawsuit.finish();
JDK 中所使用的动态代理
public interface HelloWorld {
String sayHello(String name);
}
public class HelloWorldImpl implements HelloWorld {
@Override
public String sayHello(String name) {
System.out.println(name + "Hello!");
return name;
}
}
public class DynamicProxyJDK implements InvocationHandler {
private Object target = null;
/**
* 建立原始对象和代理对象的绑定关系。
*
* @param target 原始对象
* @return 代理对象
*/
public Object bind(Object target) {
this.target = target;
// 创建被代理对象,需要指定类加载器,要代理的接口(原始对象有多个接口时,仅需要该代理对象实现的接口),代理对象(需要实现InvocationHandler接口,在invoke方法中实现代理逻辑)
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
/**
* 在代理对象中调用被代理对象的指定方法。
* 这个invoke是自动调用的。
* @param proxy 代理对象,即bind方法生成的对象
* @param method 所代理的方法
* @param args 所代理方法所需的参数
* @return 返回代理方法的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始代理方法");
Object result = method.invoke(target, args);
System.out.println("结束代理方法");
return result;
}
}
HelloWorld target=new HelloWorldImpl();
HelloWorld proxy = (HelloWorld) new DynamicProxyJDK().bind(target);
proxy.sayHello("kkkk");