设计模式学习----观察者模式(事件监听实现)

分类: Java语言 设计模式 1298人阅读 评论(0) 收藏 举报

    今天学习了新的设计模式----观察者模式,其实这种设计模式,我们早就接触过,做过GUI编程的同学肯定会知道,事件的注册监听等机制,其实这个机制的实现就是利用了观察者模式。

    可能在程序中,我们需要在某些数据变化时,其他的类做出一些响应,我们总不能开一个线程,每隔一段时间就去检测数据有没有发生变化吧,那样效率很低,我们更希望那些具有变化属性的类能够主动将自己的变化推送给,希望检测这些变化的其他类。正如我们去医院排队,不能隔两分钟就去问大夫“轮到我了吗”,而是坐在那里等大夫的通知,大家都接收到一个名字信号,叫到谁谁就去~ 而观察者就是这样一种模式,大夫的名单就是被观察者,也叫做一个 主题。每一个病人就是一个观察者。因而,观察者模式也叫做 发布订阅模式(相信使用google reader的朋友更容易理解)。

    下面 是一副来自维基百科的结构图



  可以看出来,观察者模式,是一种一对多的关系,即多个观察者监听一个主题。

  下面用一段代码给大家解释 观察者模式,通过这个例子,大家也可以看到一个缩水版的 事件监听机制的实现~我自己编写了一个交通灯的例子,应该比较形象

  首先创建一个主题接口,他声明了一个被观察者应该具有的基本方法,包括添加观察者,删除观察者,通知

  1. package observerpattern;  
  2.   
  3. /** 
  4.  * 
  5.  * @author liyang 
  6.  * 2011 08 2 
  7.  * 主题的接口 定义标准的方法 
  8.  */  
  9. public interface Subject {  
  10.     public void addListener(Listener listener);  
  11.     public void deleteListener(Listener listener);  
  12.     public void notifyListener();  
  13.       
  14.       
  15. }  

 接下来我们用一个类实现这个接口,所创建的类也就是我们具体要观察的对象了
  1. package observerpattern;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. /** 
  6.  * 
  7.  * @author liyang 
  8.  * 2011 08 2 
  9.  * SE.HIT 
  10.  * 实现主题的类,相当于图中的ConcretSubject A 
  11.  */  
  12. public class Lights implements Subject{  
  13.       
  14.     private ArrayList lights;                //collection 用于保存 观察者的集合  
  15.     private String whichLight;  
  16.     private String currentLight = "green";   //记录当前 交通灯的状态  
  17.     private int time;                        //记录交通灯持续的时间  
  18.       
  19.     public Lights(){  
  20.         lights = new ArrayList();  
  21.     }  
  22.     //实现 添加一个观察者的操作  
  23.     @Override  
  24.     public void addListener(Listener listener){  
  25.         lights.add(listener);  
  26.     }  
  27.     //实现删除一个观察者的操作  
  28.     @Override  
  29.     public void deleteListener(Listener listener){  
  30.         int index = lights.indexOf(listener);  
  31.         if( index != -1){  
  32.             lights.remove(index);  
  33.         }  
  34.     }  
  35.     //实现通知的机制 ,通知每一个观察者  
  36.     public void notifyListener(){  
  37.         int size = lights.size();  
  38.         for(int i = 0; i < size; i++){  
  39.             Listener listener = (Listener)lights.get(i);  
  40.             listener.updateSignal(whichLight,time);  
  41.         }      
  42.    }  
  43.    //更新主题状态数据的方法   
  44.     public void setLight(String whichlight,int time){  
  45.         this.whichLight = whichlight;  
  46.         this.time = time;  
  47.         //检查状态是否发生了变化  
  48.         check();  
  49.         this.currentLight = whichLight;  
  50.     }  
  51.     //实现检查状态的函数  
  52.     private void check(){  
  53.         if(! this.currentLight.equals(this.whichLight)){  
  54.             notifyListener();  
  55.         }  
  56.     }  
  57. }  

  里面涉及了一些arrayList的东西,不清楚的同学可以好好了解一下arraylist,他里面有个Fail Fast机制,从中你可以学习到更为精彩的装饰器模式,在这里不多解释了,我博客中有一篇相关的总结

  下面我们编写一个 观察者的接口,他声明观察者对通知做出的反应的方法

  1. package observerpattern;  
  2.   
  3. /** 
  4.  * @author liyang 
  5.  * 2011 08 2 
  6.  * 定义观察者接口  声明更新方法 
  7.  */  
  8. public interface Listener {  
  9.     public void updateSignal(String whichLight,int time);  
  10. }  

  最后就是编写 观察者了,本例子中我们拥有三个观察者,分别观察红黄绿等是否被打开,然后各自做出相应的通知
  1. package observerpattern;  
  2. /** 
  3.  * 
  4.  * @author liyang 
  5.  * 2011 08 02 
  6.  * SE.HIT 
  7.  * 实现红色交通灯的观察者类,相当于图中国的ConcretObserver类 
  8.  */  
  9. public class RedLightListener implements Listener{  
  10.     @Override  
  11.         //模拟接收通知,更新状态  
  12.     public void updateSignal(String whichLight, int time){  
  13.         if(whichLight.equals("red")){  
  14.             System.out.println("红灯亮了,禁止通行");  
  15.             System.out.println("持续时间: "+time);  
  16.         }  
  17.     }  
  18.       
  19. }  

  1. package observerpattern;  
  2. /** 
  3.  * 
  4.  * @author liyang 
  5.  * 2011 08 02 
  6.  * SE.HIT 
  7.  * 实现黄色交通灯的观察者类 
  8.  */  
  9. public class YellowLightListener implements Listener{  
  10.     @Override  
  11.         //模拟接收通知,更新状态  
  12.     public void updateSignal(String whichLight,int time){  
  13.         if(whichLight.equals("yellow")){  
  14.             System.out.println("黄灯亮了,请稍等");  
  15.             System.out.println("持续时间: "+ time);  
  16.         }  
  17.     }  
  18.       
  19. }  

  1. package observerpattern;  
  2.   
  3. /** 
  4.  * 
  5.  * @author liyang 
  6.  * 2011 08 02 
  7.  * SE.HIT 
  8.  * 实现绿色交通灯的观察者类 
  9.  */  
  10. public class GreenLightListener implements Listener{  
  11.     @Override  
  12.     //模拟接收通知,更新状态  
  13.     public void updateSignal(String whichLight,int time){  
  14.         if(whichLight.equals("green")){  
  15.             System.out.println("绿灯亮了,请通过");  
  16.             System.out.println("持续时间: "+time);  
  17.         }  
  18.     }  
  19.       
  20. }  

   最后就是一个演示的main了
  1. package observerpattern;  
  2.   
  3. /** 
  4.  * 
  5.  * @author liyang 
  6.  * 2011 08 02  
  7.  * SE.HIT 
  8.  * 演示设计模式---观察者模式的demo 
  9.  */  
  10. public class ObserverPattern {  
  11.   
  12.     public static void main(String[] args) {  
  13.         // TODO code application logic here  
  14.         //创建主题,被监听对象,通常是一个自身状态属性可变的类  
  15.        Lights lights = new Lights();  
  16.         
  17.        //创建三个观察者实例  
  18.       YellowLightListener yellow = new YellowLightListener();  
  19.       GreenLightListener green = new GreenLightListener();  
  20.       RedLightListener red = new RedLightListener();  
  21.       //向主题注册三个观察者,监听变化  
  22.       lights.addListener(green);  
  23.       lights.addListener(red);  
  24.       lights.addListener(yellow);  
  25.       //手动的改变交通灯的状态  
  26.       lights.setLight("red",30);  
  27.       lights.setLight("yellow"10);  
  28.       lights.setLight("green"20);  
  29.     }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值