设计模式 1 ——观察者模式

设计模式目录:

设计模式 1 ——观察者模式

一、基本定义

何谓观察者模式?观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。

在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以么可以根据需要增加和删除观察者,使得系统更易于扩展。

观察者模式又称为发布-订阅模式。

二、基本结构

首先先看观察者模式的UML类图。

分析:

Subject:目标。他把所有对观察者对戏的引用保存在一个聚集里,每一个主题都可以有多个观察者。

Observer:观察者。为所有的具体观察者定义一个接口,在得到主题的通知时能够及时的更新自己。

ConcreteSubject:具体主题。将有关状态存入具体观察者对象。在具体主题发生改变时,给所有的观察者发出通知。

ConcreteObserver:具体观察者。实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态相协调。

三、实现观察者模式

情景是这样的:在气象观测站中,它能够追踪目前的天气状况,包括温度、适度、气压。需要实现一个布告板,能够分别显示目前的状态,气象统计和简单的预报。当气象站中获取最新的测量数据时,三种布告板必须实时更新。

下面是这个案例的设计图:

编码实现:

主题接口   Subject.java

 1 /**
 2 * @Title: Subject.java
 3 * @Description: TODO
 4 * @author :Xingle
 5 * @date 2014-7-15 下午7:50:08
 6 * @version
 7 */
 8
 9 package com.dpobserver;
10
11 /**
12  *
13  * @ClassName: Subject
14  *
15  * @author Xingle
16  * @date 2014-7-15 下午7:50:08
17  */
18 public interface Subject {
19
20     /**
21      * 注册观察者模式
22      * @param observer
23      * @author xingle
24      * @data 2014-7-15 下午7:52:38
25      */
26     public void registerObserver(com.dpobserver.Observer observer);
27     /**
28      * 删除观察者
29      * @param observer
30      * @author xingle
31      * @data 2014-7-15 下午7:53:25
32      */
33     public void removeObserver(com.dpobserver.Observer observer);
34     /**
35      * 当主题状态发生改变时,这个方法需要被调用,以通知所有观察者
36      * @author xingle
37      * @data 2014-7-15 下午7:54:25
38      */
39     public void notifyObserver();
40
41 }

观察者接口  Observer.java

 1 package com.dpobserver;
 2
 3 /**
 4  * 观察者接口
 5  * @ClassName: Observer
 6  * TODO
 7  * @author Xingle
 8  * @date 2014-7-15 下午7:55:24
 9  */
10 public interface Observer {
11
12     public void update(float temp,float humidity,float presure);
13
14 }

布告板显示接口 DisplayElement.java

 1 /**
 2  * 布告板显示接口
 3  * @ClassName: DisplayElement
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-7-15 下午7:57:41
 7  */
 8 public interface DisplayElement {
 9
10     public void display();
11 }

WeatherData实现主题接口 WeatherData.java

 1 /**
 2  * @Title: WeatherData.java
 3  * @Description: TODO
 4  * @author :Xingle
 5  * @date 2014-7-15 下午7:58:47
 6  * @version
 7  */
 8
 9 package com.dpobserver;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 /**
15  *
16  * @ClassName: WeatherData TODO
17  * @author Xingle
18  * @date 2014-7-15 下午7:58:47
19  */
20 public class WeatherData implements Subject {
21     private List<com.dpobserver.Observer> observerLs;
22     private float tempterature;
23     private float pressure;
24     private float humidity;
25
26     public void setMeasurements(float tempterature, float pressure,
27             float humidity) {
28         this.tempterature = tempterature;
29         this.pressure = pressure;
30         this.humidity = humidity;
31         measurementChanged();
32     }
33
34     public WeatherData() {
35         observerLs = new ArrayList<com.dpobserver.Observer>();
36     }
37
38     /**
39      * 气象站得到更新的观测数据时,通知观察者
40      *
41      * @author xingle
42      * @data 2014-7-15 下午8:04:21
43      */
44     private void measurementChanged() {
45         notifyObserver();
46     }
47
48     /**
49      *
50      * @Description: TODO
51      * @param observer
52      * @author xingle
53      * @data 2014-7-15 下午7:59:06
54      */
55     @Override
56     public void registerObserver(com.dpobserver.Observer observer) {
57         observerLs.add(observer);
58     }
59
60     /**
61      *
62      * @Description: TODO
63      * @param observer
64      * @author xingle
65      * @data 2014-7-15 下午7:59:06
66      */
67     @Override
68     public void removeObserver(com.dpobserver.Observer observer) {
69         int i = observerLs.indexOf(observer);
70         if (i >= 0) {
71             observerLs.remove(i);
72         }
73     }
74
75     /**
76      *
77      * @Description: TODO
78      * @author xingle
79      * @data 2014-7-15 下午7:59:06
80      */
81     @Override
82     public void notifyObserver() {
83         for (int i = 0; i < observerLs.size(); i++) {
84             com.dpobserver.Observer observer = observerLs.get(i);
85             observer.update(tempterature, pressure, humidity);
86         }
87
88     }
89
90 }

布告板  CurrentCondituonDisplay.java

 1 /**
 2  * @Title: CurrentCondituonDisplay.java
 3  * @Description: TODO
 4  * @author :Xingle
 5  * @date 2014-7-15 下午8:16:15
 6  * @version
 7  */
 8
 9 package com.dpobserver;
10
11 /**
12  * 布告板
13  *
14  * @ClassName: CurrentCondituonDisplay
15  * @author Xingle
16  * @date 2014-7-15 下午8:16:15
17  */
18 public class CurrentConditionDisplay implements Observer, DisplayElement {
19     private float temperature;
20     private float humidity;
21     private float presure;
22     private Subject weatherData;
23
24     public CurrentConditionDisplay(Subject weatherData) {
25         this.weatherData = weatherData;
26         weatherData.registerObserver(this);
27     }
28
29     /**
30      *
31      * @Description:
32      * @author xingle
33      * @data 2014-7-15 下午8:16:45
34      */
35     @Override
36     public void display() {
37         System.out.println("Current conditions:" + temperature
38                 + "F degrees and " + humidity + "% humidity"+" presure :"+presure);
39     }
40
41     /**
42      *
43      * @Description: TODO
44      * @param temp
45      * @param humidity
46      * @param presure
47      * @author xingle
48      * @data 2014-7-15 下午8:16:45
49      */
50     @Override
51     public void update(float temp, float humidity, float presure) {
52         this.temperature = temp;
53         this.humidity = humidity;
54         this.presure = presure;
55         display();
56     }
57
58 }

测试程序  WeatherStation

 1 /**
 2 * @Title: WeatherStation.java
 3 * @Description: TODO
 4 * @author :Xingle
 5 * @date 2014-7-15 下午8:25:02
 6 * @version
 7 */
 8
 9 package com.dpobserver;
10
11 /**
12  *
13  * @ClassName: WeatherStation
14  * TODO
15  * @author Xingle
16  * @date 2014-7-15 下午8:25:02
17  */
18 public class WeatherStation {
19
20     public static void main(String[] args){
21         WeatherData weatherData = new WeatherData();
22         CurrentConditionDisplay conditionDisplay = new CurrentConditionDisplay(weatherData);
23         weatherData.setMeasurements(80, 65, 30.4f);
24         weatherData.setMeasurements(82, 70, 29.2f);
25         weatherData.setMeasurements(78, 78, 40.4f);
26     }
27
28 }

执行结果:

Current conditions:80.0F degrees and 65.0% humidity presure :30.4
Current conditions:82.0F degrees and 70.0% humidity presure :29.2
Current conditions:78.0F degrees and 78.0% humidity presure :40.4

四、观察者模式的优缺点

优点:

1、当两个对象之间送耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间送耦合。主题所知道只是一个具体的观察者列表,每一个具体观察者都符合一个抽象观察者的接口。主题并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。

2、观察者模式支持“广播通信”。主题会向所有的观察者发出通知。

3、观察者模式符合“开闭原则”的要求。

缺点:

1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

2、 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

3、 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

五、观察者模式的适用场所

1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

2、一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

3、一个对象必须通知其他对象,而并不知道这些对象是谁。需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

总结

1、观察者模式定义了对象之间的一对多关系。多个观察者监听同一个被观察者,当该被观察者的状态发生改变时,会通知所有的观察者。

2、观察者模式中包含四个角色。主题,它指被观察的对象。具体主题是主题子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;观察者,将对观察主题的改变做出反应;具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致。

3、主题用一个共同的接口来更新观察者。

4、观察者与被观察者之间用松耦合方式结合。

5、有多个观察者时,不可以依赖特定的通知次序。

6、使用观察者模式,可以从被观察者处推或者拉数据。

该读书笔记的代码和部分语句均来自《Head First 设计模式》

设计模式 1 ——观察者模式

时间: 2024-10-27 17:43:48

设计模式 1 ——观察者模式的相关文章

【设计模式】观察者模式

生活中,当某件事发生时,应该通知所有的相关者.例如,上课地点有变,要通知所有学习这门课的同学. 在软件设计中,当一个对象的状态发生变化是,如何通知与它相关的所有对象,就是我们今天要谈到的观察者模式. 观察者模式 概述 定义了一种一对多的依赖关系.让多个观察者对象同事监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有的观察者对象,使它们能够自动更新自己. 实际上,观察者模式所做的工作就是在解除耦合.让耦合的双方都依赖于抽象,而不是依赖于具体.从而使得各自的变化都不会影响另一边的变化. 结

设计模式:观察者模式

设计模式:观察者模式 : http://www.cnblogs.com/li-peng/archive/2013/02/04/2892116.html 观察者模式是我们经常用的一个模式,比如在用wcf做服务的时候通知客户端做一些操作一般用设计者模式. 今天做一个订报纸的小例子来理解一下观察者模式  出版者+订阅者=观察者模式 用下边的图来说就是    人民日报+订阅者=观察者模式 只要是订阅了人民日报的人,有了新报纸就会送到订阅者那里去, 当你不想订的时候取消就不订阅就不会再收到报纸了. //报

设计模式之-观察者模式

该文代码来自设计模式之惮一书. 观察者模式定义: 观察者模式也叫做发布订阅模式. 观察者模式中的角色: 1.被观察者 被观察者职责为管理观察者并通知观察者. 2.观察者 对接受到的消息进行处理. /// <summary> /// 被观察者 /// </summary> public abstract class Subject { /// <summary> /// 观察者集合 /// </summary> private List<IObserva

设计模式(16) 观察者模式(OBSERVER)C++实现

意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 动机: 将一个系统设计成一系列相互协作的类有一个常见的副作用:需要维护相关对象之间的一致性. 观察者模式定义一种交互,即发布-订阅: 一个对象当自身状态发生改变时,会发出通知,但是并不知道谁是他的接收者,但每个接收者都会接收到通知,这些接受者称为观察者. 作为对通知的响应,每个观察者都将查询目标状态,然后改变自身的状态以和目标状态进行同步. 使用场景: 使对象封装为独立的改变和使用:

&lt;&lt;Head First设计模式&gt;&gt;之观察者模式学习

1.概念 定义了对象之间的一对多依赖关系,当一个对象(主题对象)的状态改变时,它的所有依赖者(观察者对象)都会收到通知并自动更新. 2.优势 观察者模式实现了主题对象与观察者对象之间的松耦合,当有新的观察者时,无需修改主题对象的代码,只需要新的观察者对象实现接口.在程序运行的过程中,可以随时注册和删除观察者而不影响主体对象. 观察者模式使主题(Subject)对象和观察者(Observer)对象都可以被轻易地复用. 3.Java中观察者模式 Java API有内置的观察者模式,java.util

大话设计模式_观察者模式(Java代码)

观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们自己能够自动更新自己.简单描述:1个Subject类(可以是抽象类可以是接口),可以有多个具体Subject类(继承抽象Subject),此具体Subject持有多个观察者的引用,在此具体Subject状态发生变化的时候调用这些观察者的相应方法.另外,这些持有的引用是抽象的,不是具体的,而这些引用所指向的对象时具体的观察者(即需要作出更新的具体观察者,这些具体

设计模式-观察者模式(Observer Pattern)

今天看了看观察者模式,有点小小的体会,从以下3点说明之 : 1.看一下经典的观察者模式图 2.讲个故事,说一下逻辑 有一个男人(Subject),他通过一定的手段(attach)拥有了3个女人(Observer):老婆(concreteObserver1),情人(concreteObserver2),小3(concreteObserver3).这3个女人都不知情,但是都想知道男人的月收入情况.而月收入需要通过工资卡(concreteSubject)来体现.所以,每当发工资(setState)时,

常用设计模式之观察者模式 + 事件委托

常用设计模式之观察者模式 + 事件委托 作用及UML (摘自<大话设计模式>) Code 1 abstract class Subject{ 2 protected String state; 3 public void setState(String state){this.state = state;} 4 public String getState(){return this.state;} 5 6 private List<Observer> observers = ne

跟我学设计模式视频教程——观察者模式,迭代器模式

课程视频 观察者模式 迭代器模式 课程笔记 课程笔记 课程代码 课程代码 新课程火热报名中 课程介绍 跟我学设计模式视频教程--观察者模式,迭代器模式,布布扣,bubuko.com

设计模式之观察者模式C++实现

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 观察者模式结构图如下: 举例: 气象系统有三个部分分别是气象站(获取实际气象数据的物理装置),WeatherData对象(用来追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看).WeatherData对象知道如何根物理气象站联系,以取得更新信息.WeatherData对象会随机更新三个布告板的显示:目前状况(温度,湿度,气压).气象统计和天气预报.我们的工作是建立一