设计模式——代理模式
来源:互联网 发布:真正能借到钱的软件 编辑:程序博客网 时间:2024/06/15 14:51
模式介绍
代理模式:为其他对象提供一种代理以控制对这个对象的访问。
代理模式(Proxy)是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题.
分类
静态代理:代理类是在编译时就实现好的。也就是说 Java 编译完成后代理类是一个实际的 class 文件。
动态代理:代理类是在运行时生成的。也就是说 Java 编译完之后并没有实际的 class 文件,而是在运行时动态生成的类字节码,并加载到JVM中。
静态代理模式结构
模式涉及角色
RealSubject 是原对象(或称委托对象),ProxyObject是代理对象。
Subject 是委托对象和代理对象都共同实现的接口。
leave() 是委托对象和代理对象共同拥有的方法。
结构图
(图片来自网络,侵删)
示例
比如某人要请假,因为有事不能直接去请假,可以找个同事(代理对象)帮他请假。
代码实现
/** * ClassName: ProxyPattern <br/> * Function: 静态代理和动态代理<br/> * * @author gary.liu * @date 2017/5/23 */public class ProxyPattern { public static void main(String[] args){ /** * 静态代理测试 */ RealSubject realSubject = new RealSubject(); //委托对象 ProxyObject proxyObject = new ProxyObject(realSubject); //代理对象 proxyObject.leave(); }}interface Subject{ /** * 请假接口 */ void leave();}class RealSubject implements Subject { @Override public void leave(){ System.out.println("RealSubject leave request"); }}class ProxyObject implements Subject { private Subject subject; public ProxyObject(Subject subject){ this.subject = subject; } @Override public void leave(){ System.out.println("真正对象告诉代理帮他请假"); subject.leave(); System.out.println("代理告诉真正对象请假成功"); }}
动态代理
动态代理的思维模式与之前的一般模式是一样的,也是面向接口进行编码,创建代理类将具体类隐藏解耦,不同之处在于代理类的创建时机不同,动态代理需要在运行时因需实时创建.
模式结构
和上面类似,需要一个接口和实现了这个接口的真实对象类,然后还要自己定义一个类(调用处理器类,即实现 InvocationHandler 接口),这个类的目的是指定运行时将生成的代理类需要完成的具体任务(包括Preprocess和Postprocess),即代理类调用任何方法都会经过这个调用处理器类。
结构图
(图片来自网络,侵删)
代码实现
用动态代理实现上面的场景,需要自定义一个调用处理器类。
public class ProxyPattern { public static void main(String[] args){ /** * 动态代理测试 */ ProxyHandler proxyHandler = new ProxyHandler(realSubject); //动态生成代理对象 Subject proxySubject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(), proxyHandler); proxySubject.leave(); }}/** * 动态代理实现上面的例子 * */class ProxyHandler implements InvocationHandler { private Subject subject; public ProxyHandler(Subject subject){ this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args){ Object result = null; System.out.println("真正对象告诉代理帮他请假"); try{ result = method.invoke(subject, args); } catch (Exception e){ e.printStackTrace(); } System.out.println("代理告诉真正对象请假成功"); return result; }}
jdk动态代理为什么要求委托对象实现接口
//创建代理对象 static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
第二个参数是接口,表明这个代理类需要实现哪些接口。
因为 Java 的单继承特性(每个代理类都继承了 Proxy 类),只能针对接口创建代理类,不能针对类创建代理类。
手动生成的代理类写入字节数组中
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy1", RealSubject.class.getInterfaces());
然后写入class文件,用 jd-gui反编译生产的代理类如下。
public final class $Proxy1 extends java.lang.reflect.Proxy implements com.lzhenxing.javascaffold.javabase.designpattern.Subject {
模式应用
代理模式用到的地方很多,比如 spring aop 使用的便是动态代理模式,spring aop 有两种实现方式,一种是jdk动态代理(要求委托对象实现接口);另一种是字节码增强,委托对象可以不实现接口,具体实现如 cglib。
参考资料
代理模式及Java实现动态代理
《大话设计模式》
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式—代理模式
- 设计模式——代理设计模式
- 设计模式——代理设计模式
- 每日设计模式——代理模式
- 学习设计模式——代理模式
- java设计模式——代理模式
- 设计模式——策略、代理模式
- 设计模式——代理模式(Proxy)
- 设计模式——代理模式
- oracle启停脚本(HA)
- Java中Scanner的用法
- HTML写出简单的QQ注册网页
- Android 自定义圆形进度条
- A*寻路算法浅析
- 设计模式——代理模式
- apriori算法实现挖掘商品关联规则(python)
- 【PostgreSQL-9.6.3】创建、修改、删除PostgreSQL数据库
- LeetCode (Gray Code)
- wget命令
- 多线程之旅(1)—
- PHP变量在内存中的存储方式
- opencv(27)---分水岭算法及图像修补
- POJ 2299 离散化+树状数组