`

观察者模式

 
阅读更多

一模式定义

观察者模式,又称为发布/订阅模式。观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

 

二模式举例

1 模式分析

我们借用气象局高温预警来说明这一模式。



 

2观察者模式静态类图


 

3代码示例

3.1观察者接口一IObserver

Java代码  收藏代码
  1. package com.demo.observer;  
  2.   
  3. import com.demo.subject.ISubject;  
  4. /** 
  5.  * 观察者接口 
  6.  * @author  
  7.  * 
  8.  */  
  9. public interface IObserver  
  10. {  
  11.     //更新方法  
  12.     public void update(ISubject subject);  
  13. }  

3.2主题接口一ISubject

Java代码  收藏代码
  1. package com.demo.subject;  
  2.   
  3. import com.demo.observer.IObserver;  
  4.   
  5. /** 
  6.  * 主题接口(被观察者) 
  7.  *  
  8.  * @author 
  9.  *  
  10.  */  
  11. public interface ISubject  
  12. {  
  13.     /** 
  14.      * 增加观察者 
  15.      *  
  16.      * @param observer 
  17.      * @return 
  18.      */  
  19.     public boolean add(IObserver observer);  
  20.   
  21.     /** 
  22.      * 删除观察者 
  23.      *  
  24.      * @param observer 
  25.      * @return 
  26.      */  
  27.     public boolean remove(IObserver observer);  
  28.   
  29.     /** 
  30.      * 通知所有观察者更新数据 
  31.      */  
  32.     public void notifyAllObserver();  
  33.   
  34.     /** 
  35.      * 设置温度值 
  36.      *  
  37.      * @param temperature 
  38.      */  
  39.     public void setTemperature(float temperature);  
  40.   
  41.     /** 
  42.      * 获得温度预警 
  43.      *  
  44.      * @return 
  45.      */  
  46.     public String temperatureReport();  
  47. }  

3.3具体主题实现一Subject

Java代码  收藏代码
  1. package com.demo.subject;  
  2.   
  3. import java.util.Iterator;  
  4. import java.util.Vector;  
  5.   
  6. import com.demo.observer.IObserver;  
  7.   
  8. /** 
  9.  * 主题实现类(被观察者) 
  10.  *  
  11.  * @author 
  12.  *  
  13.  */  
  14. public class Subject implements ISubject {  
  15.     // 温度  
  16.     /** 
  17.      * (一)高温黄色预警信号 
  18.      *  
  19.      * 标准:连续三天日最高气温将在35℃以上。 
  20.      *  
  21.      * (二)高温橙色预警信号 
  22.      *  
  23.      * 标准:24小时内最高气温将升至37℃以上。 
  24.      *  
  25.      * (三)高温红色预警信号 
  26.      *  
  27.      * 标准:24小时内最高气温将升至40℃以上。 
  28.      */  
  29.     private float temperature;  
  30.     // 预警级别  
  31.     private String warningLevel;  
  32.   
  33.     // 保存观察者列表  
  34.     private final Vector<IObserver> vector;  
  35.   
  36.     /** 
  37.      * 构造方法 初始化观察者列表 
  38.      */  
  39.     public Subject() {  
  40.         vector = new Vector<IObserver>();  
  41.     }  
  42.   
  43.     /** 
  44.      * 增加观察者 
  45.      */  
  46.     public boolean add(IObserver observer) {  
  47.         if (observer != null && !vector.contains(observer)) {  
  48.             return vector.add(observer);  
  49.         }  
  50.   
  51.         return false;  
  52.     }  
  53.   
  54.     /** 
  55.      * 移除观察者 
  56.      */  
  57.     public boolean remove(IObserver observer) {  
  58.         return vector.remove(observer);  
  59.     }  
  60.   
  61.     /** 
  62.      * 通知所有观察者更新数据 
  63.      */  
  64.     public void notifyAllObserver() {  
  65.         System.out.println("======气象部门发布高温" + this.warningLevel + "警报!======");  
  66.         Iterator<IObserver> iterator = vector.iterator();  
  67.         while (iterator.hasNext()) {  
  68.             (iterator.next()).update(this);  
  69.         }  
  70.     }  
  71.   
  72.     /** 
  73.      * 私有方法 根据温度值设置预警级别 然后通知所有观察者 
  74.      */  
  75.     private void invoke() {  
  76.         if (this.temperature >= 35) {  
  77.             if (this.temperature >= 35 && this.temperature < 37) {  
  78.                 this.warningLevel = "黄色";  
  79.             } else if (this.temperature >= 37 && this.temperature < 40) {  
  80.                 this.warningLevel = "橙色";  
  81.             } else if (this.temperature >= 40) {  
  82.                 this.warningLevel = "红色";  
  83.             }  
  84.             // 通知所有观察者温度状况  
  85.             this.notifyAllObserver();  
  86.         }  
  87.     }  
  88.   
  89.     /** 
  90.      * 设置温度值 
  91.      *  
  92.      * @param temperature 
  93.      */  
  94.     public void setTemperature(float temperature) {  
  95.         this.temperature = temperature;  
  96.   
  97.         this.invoke();  
  98.     }  
  99.   
  100.     /** 
  101.      * 获得温度预警 
  102.      */  
  103.     public String temperatureReport() {  
  104.         return " 温度:" + this.temperature;  
  105.     }  
  106.   
  107. }  

3.4个人观察者一PersonObserver

Java代码  收藏代码
  1. package com.demo.observer;  
  2.   
  3. import com.demo.subject.ISubject;  
  4. /** 
  5.  * 个人用户观察者 
  6.  * @author  
  7.  * 
  8.  */  
  9. public class PersonObserver implements IObserver  
  10. {  
  11.   
  12.     public void update(ISubject subject)  
  13.     {  
  14.         System.out.println("个人收到高温预警:" + subject.temperatureReport());  
  15.     }  
  16.   
  17. }  

3.5政府观察者一GovernmentObserver

Java代码  收藏代码
  1. package com.demo.observer;  
  2.   
  3. import com.demo.subject.ISubject;  
  4. /** 
  5.  * 政府用户观察者 
  6.  * @author  
  7.  * 
  8.  */  
  9. public class GovernmentObserver implements IObserver  
  10. {  
  11.   
  12.     public void update(ISubject subject)  
  13.     {  
  14.         System.out.println("政府部门收到高温预警:" + subject.temperatureReport());  
  15.     }  
  16.   
  17. }  

3.6企事业单位观察者一CompanyObserver

Java代码  收藏代码
  1. package com.demo.observer;  
  2.   
  3. import com.demo.subject.ISubject;  
  4. /** 
  5.  * 企事业单位用户观察者 
  6.  * @author  
  7.  * 
  8.  */  
  9. public class CompanyObserver implements IObserver  
  10. {  
  11.   
  12.     public void update(ISubject subject)  
  13.     {  
  14.         System.out.println("企事业单位收到高温预警:" + subject.temperatureReport());  
  15.   
  16.     }  
  17.   
  18. }  

3.7让系统开始运行一Client

Java代码  收藏代码
  1. package com.demo;  
  2.   
  3. import java.util.Random;  
  4.   
  5. import com.demo.observer.CompanyObserver;  
  6. import com.demo.observer.GovernmentObserver;  
  7. import com.demo.observer.PersonObserver;  
  8. import com.demo.subject.ISubject;  
  9. import com.demo.subject.Subject;  
  10.   
  11. /** 
  12.  * 客户端应用 
  13.  *  
  14.  * @author 
  15.  *  
  16.  */  
  17. public class Client {  
  18.   
  19.     /** 
  20.      * @param args 
  21.      */  
  22.     public static void main(String[] args) {  
  23.         // 创建主题对象  
  24.         ISubject subject = new Subject();  
  25.   
  26.         // 增加企事业单位观察者  
  27.         subject.add(new CompanyObserver());  
  28.         // 增加政府用户观察者  
  29.         subject.add(new GovernmentObserver());  
  30.         // 增加个人用户观察者  
  31.         subject.add(new PersonObserver());  
  32.   
  33.         Random random = new Random();  
  34.         int i = 0;  
  35.         while (++i < 10) {  
  36.             // 设置随机温度  
  37.             subject.setTemperature(random.nextInt(45));  
  38.         }  
  39.     }  
  40. }  

4运行结果

======气象部门发布高温黄色警报!======

企事业单位收到高温预警: 温度:35.0

政府部门收到高温预警: 温度:35.0

个人收到高温预警: 温度:35.0

======气象部门发布高温红色警报!======

企事业单位收到高温预警: 温度:43.0

政府部门收到高温预警: 温度:43.0

个人收到高温预警: 温度:43.0

======气象部门发布高温橙色警报!======

企事业单位收到高温预警: 温度:37.0

政府部门收到高温预警: 温度:37.0

个人收到高温预警: 温度:37.0

 

三该模式设计原则

1"开——闭"原则

2单一职责原则

3依赖倒置原则

 

四使用场合

1当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,需要将这两个方面分别封装到独立对象中,彼此独立地改变和复用的时候。

2当一个系统中一个对象的改变需要同时改变其他对象内容,但又不知道待改变对象到底有多少个的时候。

3当一个对象的改变必须通知其他对象做出相应的变化,但是不能确定通知对象是谁的时候。

 

五"推数据"静态类图

所谓"推数据",就是当被观察对象发生改变时,将相关数据通过参数形式传递给观察者,这就形成了被观察者"推数据"给观察者,静态类图如下:



 

六"拉数据"静态类图

所谓"拉数据",观察者对象含有一个对被观察者对象实例的引用,当被观察者对象发生变化时,不会传递任何数据给观察者,而由观察者根据被观察者对象实例的引用主动获取相关的数据,这就形成了观察者主动从被观察对象中"拉数据“,静态类图如下:



 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics