代理模式,薪资翻倍
public Proxy() {
//构造函数中初始化一个要被代理的对象
subject = new RealSubject("default");
}
/*可以构造函数中传入被代理者/
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
beforeRequest();
subject.request();
afterRequest();
}
private void beforeRequest() {
System.out.println("在访问实际的被代理者对象方法之前做一些事情");
}
private void afterRequest() {
System.out.println("在访问实际的被代理者对象方法之后做一些事情");
}
}
public class Client {
public static void main(String[] args) {
Proxy subjectProxy = new Proxy();
subjectProxy.request();
System.out.println();
subjectProxy = new Proxy(new RealSubject("new"));
subjectProxy.request();
}
}
输出:
客户端在使用的时候,对 RealSubject 的请求完全由 Proxy 代为处理,Proxy 代理请求的时候可以在之前或之后执行自己的个性化的方法。对于实际的被代理者对象 RealSubject 的创建,可以完全放在 Proxy 的构造函数内部,也可以外部创建好之后再传入代理对象,这需要根据实际需求确定,如果你想要屏蔽客户端对真实的被代理者角色的访问,那么这时可以将需要的参数传入代理者内部来创建对象。
强制代理
顾名思义,强制代理就是要强制使用代理对真实对象进行访问,如果不使用代理则没有办法访问到被代理的对象。之所以这么做,是因为在某些情况下,我们的被代理者身份安全级别比较高,不希望别人直接访问到真实对象,比如我写了一个算法类,或者是系统的一个核心类,不希望客户直接去调用它,而必须通过代理来访问。
示例代码改造如下:
public class RealSubject implements Subject {
private String name;
private static Proxy proxy;
private RealSubject(String name) {
this.name= name;
}
public static Proxy getProxy() {
if (proxy == null) {
proxy = new Proxy(new RealSubject("param"));
}
return proxy;
}
@Override
public void request() {
System.out.println("执行实际的被代理者对象的方法 "+name);
}
}
public class Client {
public static void main(String[] args) {
Proxy proxy = RealSubject.getProxy();
proxy.request();
}
}
在上面代码中,我们直接将 RealSubject 的构造函数私有化,这样客户端连 new 一个被代理者对象的机会都没有,也就没有办法去直接调用被代理者对象的任何方法,客户端只能通过静态方法 getProxy()获取到一个代理对象,通过该对象进行访问。这就好比你要想访问明星,则先要跟他的经纪人打交道。
虚拟代理
这里提到的“虚拟代理”其实就是延迟初始化,并没有听上去那么复杂,至于为啥叫这个名字,我也不清楚是谁最初这样叫的,可能是业内约定成俗了,可以不用管它,我们知道是啥就行了。
示例代码:
public class Proxy implements Subject {
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
if (subject == null) {
subject = new RealSubject("param");
}
subject.request();
}
}
代码跟之前的唯一区别就是将对象的初始化放到了调用的时候,这对于创建开销比较大的对象是有用的,因为你不需要一开始就去创建它们,只有当真正被使用到的时候才会创建。
动态代理
java 的 api 为我们提供了两个类可以实现代理模式:Proxy 和 InvocationHandler, 通过利用 Java 提供的类实现的代理称为动态代理,下面是类图:
其中 Proxy 是一个类,由 jdk 提供,客户端无需实现,InvocationHandler 是一个接口,由 jdk 提供,客户端只需要创建实现类实现该接口即可。
示例代码:
public class MyInvocationHandler implements InvocationHandler {
private Object object;
public MyInvocationHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] a
rgs) throws Throwable {
return method.invoke(this.object, args);
}
}
public class DynamicProxy {
public static <T> T newProxyInstance(Subject subject) {
ClassLoader classLoader = subject.getClass().getClassLoader();
Class<?>[] interfaces = subject.getClass().getInterfaces();
InvocationHandler handler = new MyInvocationHandler(subject);
return (T) Proxy.newProxyInstance(classLoader, interfaces, handler);
}
评论