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. CentOS7 增加tomcat 启动,停止,使用systemctl进行配置

    1,centos7 使用 systemctl 替换了 service命令 参考:redhat文档: https://access.redhat.com/documentation/en-US/Red_ ...

  2. 测试秒杀新版本3.5 stieserver cms

    EXP: 直接访问UserCenter/login.aspx 用户名处输入: 123′insert into bairong_Administrator([UserName],[Password],[ ...

  3. 向量时钟算法简介——本质类似MVCC

    转自:http://blog.chinaunix.net/uid-27105712-id-5612512.html 一.使用背景 先说一下需要用到向量时钟的场景.我们在写数据时候,经常希望数据不要存储 ...

  4. sourceTree 更新svn提示can't locate SVN/Core.pm

    装了sourceTree一直没有怎么用,今天试着用用,居然报错 can't locate SVN/Core.pm 详细报错如下: Can't locate SVN/Core.pm in @INC (y ...

  5. Android启动模式(三种)

    1,标准启动模式 通过任务栈,每点一次button,将每一个实例都压入,然后点返回键时候,就弹出之前压入的实例. 每一次的地址都是不同的 测试代码:通过创建一个button和textView来显示本身 ...

  6. hdu 2079

    ps:昨天刚做了个母函数的,觉得不太熟,今天又是母函数..很好.. 代码: #include "stdio.h" #include "string.h" ]; ...

  7. php 得到一个文件夹下的所有文件,包括子文件中的文件

    $dir = FCPATH."uploads/attachment/"; $this->getFiles($dir); function getFiles($dir) { $ ...

  8. Oracle的内存结构

    备注:本图片截图自“炼数成金” Oracle的体系结构分为内存结构.进程,磁盘文件. 内存结构分为SGA, PGA.SGA是系统全局区,是所有的用户共享区,PGA是某个用户的私有区. SGA分为sha ...

  9. ffmepg-nginx-nginx-rtmp-module配置脚本

    把上个月写的的配置脚本贴一下: #!/bin/bash #version:-- #create by itn #dis: this is used to auto install ffmpeg+ngi ...

  10. HDU 1536 & 1944

    http://acm.hdu.edu.cn/showproblem.php?pid=1536 http://acm.hdu.edu.cn/showproblem.php?pid=1944 一样的题 题 ...