大话设计模式——代理模式
2017-08-17 23:02
197 查看
需求
小明一直暗恋着小花,想了很久,下定决心要向她表白,对她说出我爱你 :)鉴于笔记整理需要,将原文的故事背景进行改编。
初步实现
妹子类:public class Meizi { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
汉子类:
public class Hanzi { private Meizi meizi; public Hanzi(Meizi meizi) { this.meizi = meizi; } public void sayLoveToHer() { System.out.println("I love you, " + meizi.getName() + "!"); } }
客户端类:
public class Client { public static void main(String[] args) { Meizi xiaohua = new Meizi(); xiaohua.setName("小花"); Hanzi xiaoming = new Hanzi(xiaohua); xiaoming.sayLoveToHer(); } }
运行结果:
分析
大家都知道,现实情况小明很有可能有点害羞,不好意思直接对小花说我爱你。所以,小明想了个办法,决定让小红(小花的闺密)转述,简单来说,小红是个“僚机”。那么,这样的实现方式小红充当一个代理。代理模式
定义:为其他对象提供一种代理以控制对这个对象的访问。通过引入一个新的对象,来实现对真实对象的操作或者将新的对象作为真实对象的一个替身。即代理对象。结构示意图:
代理模式代码实现如下:
Subject类:定义了RealSubject和Proxy的公用接口,这样就可以在任何使用RealSubject的地方使用Proxy;
public abstract class Subject{ public abstract void request(); }
RealSubject类:定义了Proxy所代表的真实实体;
public class RealSubject extends Subject{ public void request(){ System.out.println("真实的请求"); } }
Proxy类:保存了一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这种代理就可以用来替代实体;
public class Proxy extends Subject{ private RealSubject realSubject; public void request(){ if(realSubject != null) realSubject = new RealSubject(); realSubject.request(); } }
客户端代码:
public class Client { public static void main(String[] args) { Proxy proxy = new Proxy(); proxy.request(); } }
再次实现
了解代理模式的实现过程,我们很容易写出运用代理模式的案例实现。小红作为代理对象,代替小明去表白,所以表白是俩者共同的功能接口,小明和小红都要去实现这个功能。定义接口:表白
public interface IExpress { void sayLoveToHer(); }
汉子实现接口;
public class Hanzi implements IExpress{ private Meizi meizi; public Hanzi(Meizi meizi) { this.meizi = meizi; } @Override public void sayLoveToHer() { System.out.println("I love you, " + meizi.getName() + "!"); } }
代理类实现接口;
public class Proxy implements IExpress { private Hanzi hanzi; public Proxy(Hanzi hanzi) { this.hanzi = hanzi; } @Override public void sayLoveToHer() { System.out.println("昨天,有个汉子和我说:"); hanzi.sayLoveToHer(); } }
客户端。
public class Client { public static void main(String[] args) { Meizi xiaohua = new Meizi(); xiaohua.setName("小花"); Proxy xiaohong = new Proxy(new Hanzi(xiaohua)); xiaohong.sayLoveToHer(); } }
运行结果
再次分析
可能已经发现了,代理对象小红如实的转达了小明的意思,那么如果小明和小红关系很好,可能小红会在小花面前多美言几句,这其实就是代理模式可以增强原本类的功能。例如,在JavaEE中,我们会通过Spring来管理Hibernate的事务,我们并没有去写开启事务、关闭事务的语句,但其实这一切都在背后帮我们做了,我们仅仅需要在Spring的配置文件中去配置好Hibernate的事务管理,其实这背后就是代理模式。深入代理模式
上面所实现的是一般的静态代理模式,下面介绍一下JDK动态代理:动态代理和上面静态代理实现区别就是少一个代理类Proxy的实现,而在客户端动态实现功能。
因此,可以看出静态代理在如下情况显得捉襟见肘:
代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
JDK动态代理实现
因为创建出来的这个代理类,一定是接口的子类,所以JDK动态代理一定要有接口,并且真实的业务类要实现该接口。客户端代码:
public class Client { public static void main(String[] args) { Meizi xiaohua = new Meizi(); xiaohua.setName("小花"); IExpress xiaoming = new Hanzi(xiaohua); IExpress xiaohong = (IExpress) Proxy.newProxyInstance(xiaoming.getClass().getClassLoader(), xiaoming.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("sayLoveToHer")){ System.out.println("昨天,小明和我说:"); Object obj = method.invoke(xiaoming, args); System.out.println("我觉得很不错,答应他吧!"); return obj; } return method.invoke(proxy, args); } }); xiaohong.sayLoveToHer(); } }
运行结果:
最后
动态代理还有Cglib动态代理,在Spring中经常用到。Spring这个框架运用到的设计模式确实非常多,这里推荐前几日掘金上的一篇文章,关于代理模式:JAVA中的静态代理、动态代理以及CGLIB动态代理个人公众号:每日推荐一片技术博客,坚持每日进步一丢丢…欢迎关注,想建个微信群,主要讨论安卓和Java语言,一起打基础、用框架、学设计模式,菜鸡变菜鸟,菜鸟再起飞,愿意一起努力的话可以公众号留言,谢谢…
相关文章推荐
- 《大话设计模式》java实现之代理模式
- 《大话设计模式》学习笔记4:代理模式
- 大话设计模式之代理模式
- 大话设计模式之代理模式(二)与JDK动态代理原理
- 大话设计模式,让你的代码更完美3---代理模式
- 【读书笔记】大话设计模式—代理模式
- 大话设计模式3 装饰模式 代理模式
- 大话设计模式_代理模式
- 《大话设计模式》读书笔记(C++代码实现) 第七章:代理模式
- 代理模式 -- 大话设计模式
- 大话设计模式-----(二)装饰模式、代理模式
- 大话设计模式之代理模式
- 大话设计模式之代理模式
- 读前辈的大话设计模式(五)之代理模式,抒自己的读后感
- 第7章 为别人做嫁衣----代理模式 大话设计模式
- 《大话设计模式》--为别人做稼衣--代理模式<Proxy>(7)
- 5.大话设计模式-代理模式
- 【大话设计模式】——代理模式
- 《大话设计模式》第三篇之代理模式
- 大话设计模式C++实现-第7章-代理模式