学习设计模式 - 代理模式
学习设计模式 - 代理模式
一丶定义
代理模式为另一个对象提供替身或者占位符以控制对这个对象访问, 被代理的对象可以是远程的对象、创建开销大的对象、需要安全控制的对象
二丶理解
2.1) 当一个对象除了处理真正的业务逻辑之外, 还需要增加额外的处理,如事务,打印日志等等, 如果将这些额外逻辑放到原对象中,会造成职责不清晰.
这时可以使用代理对象代理该对象, 代理对象实现额外逻辑, 真正的业务逻辑则委托给被代理对象处理.这样可以使得职责清晰.
2.2) 为另一个对象提供一个替身或占位符以控制对这个对象的访问.这也是代理模式和装饰者模式之间的重要区别
当一个对象是大对象或者消耗资源的对象, 为提高系统性能, 可以使用代理对象暂时替代该对象, 到真正需要的时候才生成该对象.
当权限不够时,可以使用代理对象限制对该对象的访问.
三丶静态代理
a. 主题
public interface Subject { void request(); }
b. 真实主题
public class RealSubject implements Subject { @Override public void request() { System.out.println("真正业务逻辑..."); } }
c. 代理
public class Proxy implements Subject { private Subject subject; public Proxy(Subject subject) { this.subject = subject; } @Override public void request() { System.out.println("增加事务..."); subject.request(); } }
d. 场景类
/** * 静态代理 * * 缺点: * 相同的代理方法,却要写多个代理类 * @author TimFruit * @date 19-5-25 下午10:15 */ public class Client { public static void main(String[] args) { Proxy proxy=new Proxy(new RealSubject()); proxy.request(); Proxy2 proxy2=new Proxy2(new RealSubject2()); proxy2.request(); } }
运行结果为:
增加事务...
真正业务逻辑...
增加事务...
真正的业务处理2...
还有类似的代码Proxy2没有贴出来, 完整代码可以点此查看
四丶JDK动态代理
由上面代码可知, 使用静态代理需要为每个"被代理的类", 实现代理类, 当代理类实现方法相同时, 将会产生很多繁琐重复的代码, 因此有了动态代理, 动态代理一般有两种常用的实现, 一种是jdk动态代理, 一种是cglib动态代理. 这里展示的是jdk动态代理.
/** * 实现jdk自带的接口 * 写一个较为通用的"切面"类 * @author TimFruit * @date 19-5-26 上午10:57 */ public class ProxyInvocationHandler implements InvocationHandler { private Object target; public ProxyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("增加事务..."); return method.invoke(target, args); } }
场景类:
/** * JDK动态代理 * <p> * 好处是写一个较为通用的"切面"类就可以了, 动态生成对应的代理类, 减少代码量 * * @author TimFruit * @date 19-5-26 上午11:00 */ public class Client { public static void main(String[] args) { RealSubject subject=new RealSubject(); InvocationHandler proxyInvocationHandler=new ProxyInvocationHandler(subject); //动态生成代理类 Subject subjectProxy= (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, proxyInvocationHandler); subjectProxy.request(); RealSubject2 subject2=new RealSubject2(); InvocationHandler proxyInvocationHandler2=new ProxyInvocationHandler(subject2); // 动态生成代理类 Subject2 subjectProxy2= (Subject2) Proxy.newProxyInstance(RealSubject2.class.getClassLoader(), new Class[]{Subject2.class}, proxyInvocationHandler2); subjectProxy2.request(); } }
运行结果为:
增加事务...
真正业务逻辑...
增加事务...
真正的业务处理2...
完整代码点此查看
学习资料:
<Head First 设计模式>
<设计模式之禅>
人生没有彩排,每一天都是现场直播