java事件委托

  • Post author:
  • Post category:java


本案例设计到设计模式中的观察者模式(订阅发布)

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

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

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

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

代码及说明如下:

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

Code:



  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的方法

Code:



  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。通知所有需要放哨的学生:老师来了

Code:



  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

Code:



  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

Code:



  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

Code:



  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. }

测试代码:

Code:



  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();
  19. 笔者总结:事件委托的本质是,我们把所有操作都当做是调用某一个实例的某一个方法(有时需要参数),那么通过java的反射,穿入实例和方法名就可以做统一的处理。



版权声明:本文为pj10405135原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。