http://blog.csdn.net/yanshujun/article/details/6494447

用java语言实现事件委托模式

2010-04-27 00:04 2206人阅读 评论(11) 收藏 举报

事件委托模式是一个比较常用的设计模式,但是Java语言本身没有对其做一定的封装,因此实现起来有一定难度(了解原理后很简单),相比之下.NET就容易了很多。

身为一个Java爱好者,怎么向这样一个小困难低头,但是上网搜索,却没发现相关解决方案,得,自己来做一个封装吧。

其实结合例子更好,那么我就用一个小例子来引出这种设计模式。

一个班级,有两类学生,A类:不学习,玩,但是玩的东西不一样,有的是做游戏,与的是看电视(有点不合理)

B类:放哨的学生,专门看老师的动向,如果老师进班了就立即通知大家。

如此就形成了一个需求,放哨的学生要通知所有玩的学生:老师来了,而不同的学生有不同的反应,有的马上把电视关闭,有的停止玩游戏。

设计的要求如下,让A类学生和B类学生完全解耦,即A类完全不知道B类的学生,却可以通知B类的学生。

代码及说明如下:

Event 类,定义了一个事件类:

  1. package lnurd.test;
  2. import java.lang.reflect.Method;
  3. import java.util.Date;
  4. public class Event {
  5. //要执行方法的对象
  6. private Object object;
  7. //要执行的方法名称
  8. private String methodName;
  9. //要执行方法的参数
  10. private Object[] params;
  11. //要执行方法的参数类型
  12. private Class[] paramTypes;
  13. public Event(){
  14. }
  15. public Event(Object object,String methodName,Object...args){
  16. this.object=object;
  17. this.methodName=methodName;
  18. this.params=args;
  19. contractParamTypes(this.params);
  20. }
  21. //根据参数数组生成参数类型数组
  22. private void contractParamTypes(Object[] params){
  23. this.paramTypes=new Class[params.length];
  24. for(int i=0;i<params.length;i++){
  25. this.paramTypes[i]=params[i].getClass();
  26. }
  27. }
  28. public Object getObject() {
  29. return object;
  30. }
  31. //若干setter getter省略
  32. public void setParamTypes(Class[] paramTypes) {
  33. this.paramTypes = paramTypes;
  34. }
  35. //执行该 对象的该方法
  36. public void invoke() throws Exception{
  37. Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes());
  38. if(null==method){
  39. return;
  40. }
  41. method.invoke(this.getObject(), this.getParams());
  42. }
  43. }

EventHandler类,若干Event类的载体,同时提供一个执行所有Event的方法

  1. package lnurd.test;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class EventHandler {
  5. //是用一个List
  6. private List<Event> objects;
  7. public EventHandler(){
  8. objects=new ArrayList<Event>();
  9. }
  10. //添加某个对象要执行的事件,及需要的参数
  11. public void addEvent(Object object,String methodName,Object...args){
  12. objects.add(new Event(object,methodName,args));
  13. }
  14. //通知所有的对象执行指定的事件
  15. public void notifyX() throws Exception{
  16. for(Event e : objects){
  17. e.invoke();
  18. }
  19. }
  20. }

放哨的学生:这里先抽象出一个抽象类,因为放哨的人有尽职尽责的,也有马马虎虎的,

但是他们有功能的方法1。增加需要帮忙放哨的学生  2。通知所有需要放哨的学生:老师来了

  1. package lnurd.test;
  2. public abstract class Notifier {
  3. private EventHandler eventHandler=new EventHandler();
  4. public EventHandler getEventHandler() {
  5. return eventHandler;
  6. }
  7. public void setEventHandler(EventHandler eventHandler) {
  8. this.eventHandler = eventHandler;
  9. }
  10. //增加需要帮忙放哨的学生
  11. public abstract void addListener(Object object,String methodName,Object...args);
  12. //告诉所有要帮忙放哨的学生:老师来了
  13. public abstract void notifyX();
  14. }

接着是放哨人的具体实现了,这里仅实现两个

1尽职尽责的放哨人GoodNotifier

2马马虎虎的放哨人BadNotifier

  1. package lnurd.test;
  2. public class GoodNotifier extends Notifier {
  3. @Override
  4. public void addListener(Object object, String methodName, Object... args) {
  5. System.out.println("有新的同学委托尽职尽责的放哨人!");
  6. this.getEventHandler().addEvent(object, methodName, args);
  7. }
  8. @Override
  9. public void notifyX() {
  10. System.out.println("尽职尽责的放哨人告诉所有需要帮忙的同学:老师来了");
  11. try{
  12. this.getEventHandler().notifyX();
  13. }catch(Exception e){
  14. e.printStackTrace();
  15. }
  16. }
  17. }
  18. //对于BadNotifier代码类似,不再复述.

接下来是玩游戏的学生:PlayingGameListener

  1. package lnurd.test;
  2. import java.util.Date;
  3. public class PlayingGameListener {
  4. public PlayingGameListener(){
  5. System.out.println("我正在玩游戏 开始时间"+new Date());
  6. }
  7. public void stopPlayingGame(Date date){
  8. System.out.println("老师来了,快回到座位上,结束时间"+date);
  9. }
  10. }

在接下来是看电视的学生WatchingTVListener

  1. package lnurd.test;
  2. import java.util.Date;
  3. public class WatchingTVListener {
  4. public WatchingTVListener(){
  5. System.out.println("我正在看电视 "+new Date());
  6. }
  7. public void stopWatchingTV(Date date){
  8. System.out.println("老师来了,快关闭电视 。 结束时间"+date);
  9. }
  10. }

测试代码:

  1. //创建一个尽职尽责的放哨者
  2. Notifier goodNotifier=new GoodNotifier();
  3. //创建一个玩游戏的同学,开始玩游戏
  4. PlayingGameListener playingGameListener=new PlayingGameListener();
  5. //创建一个看电视的同学,开始看电视
  6. WatchingTVListener watchingTVListener=new WatchingTVListener();
  7. //玩游戏的同学告诉放哨的同学,老师来了告诉一下
  8. goodNotifier.addListener(playingGameListener, "stopPlayingGame",new Date());
  9. //看电视的同学告诉放哨的同学,老师来了告诉一下
  10. goodNotifier.addListener(watchingTVListener, "stopWatchingTV",new Date());
  11. try{
  12. //一点时间后
  13. Thread.sleep(1000);
  14. }catch(Exception e){
  15. e.printStackTrace();
  16. }
  17. //老师出现,放哨的人通知所有要帮忙的同学:老师来了
  18. goodNotifier.notifyX();

点评:

1。放哨者完全不知道做游戏者的存在,完全解耦。(当然,功劳归功于Event和EventHandler,且这两个类具有通用性)

2。老师来了后游戏者停止游戏回到座位,看电视着关闭电视。(一次通知,执行了不同类的不同方法)

3。扩展性很高,再来一个打篮球的学生就先写个打篮球学生类,并在测试代码中告诉放哨者一下就好,放哨者完全没有变。重用性好

PS:写文档是在太累了,是写代码的好几倍,其实应该将Event 和EventHandler抽象成接口最后,实在太晚了,留给大家发挥吧。

 

猜你在找
 
 
查看评论
11楼 wangxiaoli888 2010-05-13 07:16发表 [回复] [引用] [举报]
[惊讶]
10楼 pengchengjiji 2010-05-10 22:08发表 [回复] [引用] [举报]
我也在看Java设计模式
9楼 cjn19aijia 2010-05-10 14:51发表 [回复] [引用] [举报]
等段时间学java,学习了。谢谢分享
8楼 lyboy8 2010-05-08 16:47发表 [回复] [引用] [举报]
学习一下....最近在学c#的委托..事件...
7楼 Myxiao7 2010-05-07 13:07发表 [回复] [引用] [举报]
[惊讶]
6楼 yanshujun 2010-04-30 21:57发表 [回复] [引用] [举报]
<div class="quote"><span class="q"><b> 付菁(职业指导)<img src='image/group/admin.gif' border=0></b>: 感谢分享,你的文章已经推荐到学生大本营首页。</span></div>[可爱]
5楼 imlsb 2010-04-30 18:05发表 [回复] [引用] [举报]
写得很好,学习了!
4楼 doo1314 2010-04-29 12:01发表 [回复] [引用] [举报]
接帖来分
3楼 gy3058 2010-04-29 10:55发表 [回复] [引用] [举报]
很好。[大笑]
2楼 doo1314 2010-04-28 13:00发表 [回复] [引用] [举报]
学习
1楼 fujingselene 2010-04-28 10:58发表 [回复] [引用] [举报]
感谢分享,你的文章已经推荐到学生大本营首页。
 
 
您还没有登录,请[登录][注册]
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

用java语言实现事件委托模式的更多相关文章

  1. 设计模式(Java语言)- 工厂方法模式

    前言 在介绍工厂方法模式之前,我们需要知道这个设计模式是什么,解决了什么样的问题?在上一篇博客 设计模式(Java语言)- 简单工厂模式 介绍了简单工厂模式,然后总结了简单工厂模式的缺点: 1.当新增 ...

  2. 设计模式(Java语言)- 简单工厂模式

    简单工厂模式有称为静态工厂模式,属于设计模式中的创建型模式.简单工厂模式通过对外提供一个静态方法来统一为类创建实例.简单工厂模式的目的是实现类与类之间解耦,其次是客户端不需要知道这个对象是如何被穿创建 ...

  3. 在myeclipse中使用Java语言进行spark Standalone模式应用程序开发

    一.环境配置 Myeclipse中虽然已经集成了maven插件,但是由于这个插件版本较低,建立maven project会出现错误. 解决办法:自己到官网http://maven.apache.org ...

  4. jdbc 加载数据库驱动如何破坏双亲委托模式

    导读      通过jdbc链接数据库,是每个学习Java web 方向的人必然一开始会写的代码,虽然现在各路框架都帮大家封装好了jdbc,但是研究一下jdbc链接的套路还是很意义     术语以及相 ...

  5. 《JAVA设计模式》之原型模式(Prototype)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述原型(Prototype)模式的: 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办 ...

  6. Java类加载双亲委托模式优点

    启动类加载器可以抢在标准扩展类加载器之前去装载类,而标准扩展类装载器可以抢在类路径加载器之前去加载那个类,类路径装载器又可以抢在自定义类装载器之前去加载类.所以Java虚拟机先从最可信的Java核心A ...

  7. Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)

    一.回调函数 为什么首先会讲回调函数呢?因为这个是理解监听器.观察者模式的关键. 什么是回调函数 所谓的回调,用于回调的函数. 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数. ...

  8. 设计模式(Java语言)- 原型模式

    原型模式(Prototype Pattern)也有人将原型模式称为克隆模式,是属于创造型设计模式,用于创建重复的对象,提供了一种创建对象的最佳方式.原型模式需要实现Cloneable接口,来实现对象的 ...

  9. vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结

    vue—你必须知道的   目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...

随机推荐

  1. VMware克隆后,网卡若干问题

    网卡问题 由于克隆虚拟机,vmware只是修改了虚拟机的名字等信息,并没有修改虚拟硬盘中的任何信息, 导致克隆后网卡的MAC地址和操作系统中记录的mac地址不符,导致eth0启动不起来. 操作系统记录 ...

  2. js问题解释

    今天群里有人问一个js问题,现列出以便其他人参考. Function.prototype.curry=function(){ var slice=Array.prototype.slice, args ...

  3. java开发前奏

    做java开发当然少不了jdk(java开发工具),那么今天就介绍一下jdk的安装和配置. JDK官网下载地址(建议去官网下载,免费的) http://www.oracle.com/technetwo ...

  4. iOS开发网络篇—监测网络状态

    iOS开发网络篇—监测网络状态 一.说明 在网络应用中,需要对用户设备的网络状态进行实时监控,有两个目的: (1)让用户了解自己的网络状态,防止一些误会(比如怪应用无能) (2)根据用户的网络状态进行 ...

  5. 通过MD5排除重复文件

    今天下载了好多美女图片壁纸,可是看了一下发现好多图片重复了,有强迫症的我必须把重复的都给剔除掉,首先想到的当然是百度了,问问度娘有没有什么图片去重的工具,搜了一下还真有.奈何本人智商捉急用不来这高级的 ...

  6. 什么是CPA, CPS, CPT?

    在互联网上或移动端进行产品推广时,经常听到很多术语,什么CPA,CPS,CPT等等.不知是怎么来的,今天网上搜一下术语,在这里做一下笔记. CPA(Cost Per Action) 每行动成本. CP ...

  7. jQuery.extend源码深层分析

    在网站的开发中,经常会自己写一些jQuery插件来方便使用,其中自然少不了一个关键的方法->jQuery.extend(),使用这个方法来扩展jQuery对象. 那么今天就来讲讲这个函数的实现原 ...

  8. MySQL文件目录格式及存放位置

    了解MYSQL的都知道,在MYSQL中建立任何一张数据表,在其数据目录对应的数据库目录下都有对应表的.frm文件,.frm文件是用来保存每个数据表的元数据(meta)信息,包括表结构的定义等,.frm ...

  9. js限制文本框只能输入整数或者带小数点[转]

    这篇文章是关于js限制文本框只能输入整数或者带小数点的内容,以下就是该内容的详细介绍. 做表单验证的时候是否会碰到验证某个输入框内只能填写数字呢,仅允许输入整数数字或者带小数点的数字.下面这段代码也许 ...

  10. UIkit框架之UISegmentedControl

    1.继承链:UIcontrol:UIview:uiresponder:NSObject 2.初始化 (1)- (instancetype)initWithItems:(NSArray *)items ...