目录
一、代理模式的定义
为另一个对象提供一个替身以控制对这个对象的访问
二、类图
1、抽象对象角色(上图中的Subject接口)
声明了目标对象和代理对象的共同接口,作用:任何可以使用目标对象的地方都可以使用代理对象
2、目标对象角色(上图中的RealSubject)
定义了代理对象所代表的目标对象
3、代理对象角色(上图中的Proxy)
代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象
三、例子
1、抽象对象角色
/**
* 抽象对象角色:Server
* 声明了目标对象和代理对象的共同接口,继而在任何可以使用目标对象的地方都可以使用代理对象
*/
public interface Server {
public String getPageTitle(String url);
}
2、目标对象角色
/**
* 目标对象角色:SinaServer
* 定义了代理对象所代表的目标对象
*/
public class SinaServer implements Server {
@Override
public String getPageTitle(String url) {
if ("http://www.sina.com.cn/".equals(url)) {
return "新浪首页";
} else if ("http://http://sports.sina.com.cn/".equals(url)) {
return "新浪体育_新浪网";
}
return "无页面标题";
}
}
3、代理对象角色
/**
* 代理对象角色:NginxProxy
* 代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;
* 代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象
*/
public class NginxProxy implements Server {
private Server server;
public NginxProxy(Server server) {
this.server = server;
}
@Override
public String getPageTitle(String url) {
return "页面标题:" + server.getPageTitle(url);
}
}
4、测试
public class ProxyTest {
public static void main(String[] args) {
Server sinaServer = new SinaServer();
Server nginxProxy = new NginxProxy(sinaServer);
//用户直接和nginxProxy代理打交道
System.out.println(nginxProxy.getPageTitle("http://www.sina.com.cn/"));
//运行结果:页面标题:新浪首页
}
}
四、动态代理例子
1、代理类得实现 InvocationHandler 接口
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class NginxInvocationHandler implements InvocationHandler {
private Object obj;
public NginxInvocationHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
StringBuilder sb = new StringBuilder();
sb.append("页面标题:");
sb.append(method.invoke(obj, args));
return sb.toString();
}
}
2、测试
public class DynamicProxyTest {
public static void main(String[] args) {
Server sinaServer = new SinaServer();
InvocationHandler invocationHandler = new NginxInvocationHandler(sinaServer);
Server proxy = (Server) Proxy.newProxyInstance(Server.class.getClassLoader(),
new Class[] { Server.class },invocationHandler);
System.out.println(proxy.getPageTitle("http://www.sina.com.cn/"));
}
}
3、思考:(1)例三和例四在实现上有何不同?(2)动态代理的原理是什么?(3)例四如果用Cglib实现,怎么做?与Cglib区别?
参考文章:https://www.cnblogs.com/xrq730/p/4907999.html(例子是参考这篇文章的,做了简单修改)