设计模式(Design pattern)是什么?它是一套由四人组(The Gang of Four, [1]的作者)总结出来的软件设计框架。其目的是为了提高代码的可重用性,增强系统的可维护性和代码的易读性。在四人组的《Design Patterns》一书中提到了23中最常用的设计模式,大致可以分为三大类:
  1. 创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;
  2. 结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥连接模式、组合模式、享元模式;
  3. 行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

  关于上面23中设计模式的大概介绍可以参考博客[2]。

  从上面的分类可以看出观察者模式是一种对象的行为型模式。它也被称之为发布-订阅(Publish-Subscribe)模式、模型视图(Model-View)模式或源-监听器(Source-Listener)模式[3]。通俗的说,观察者模式涉及到(至少)两个对象。其一是观察者,其二是被观察者。例如在一个RSS订阅系统中,发布方充当被观察者角色,而订阅方则充当了观察者角色。一般来说,观察者与被观察者是多对一的关系。即多个监听器可以同时监听某一主题对象。当主题对象状态发生改变时,监听器对象也会自动的更新自身状态。
 
  这篇博客主要是从一个实际的例子出发,来简单的说明Java(Android)、Objective-C(iOS)、C#(Windows Phone)三种面向对象编程语言对观察者模式的实现。
 

观察者模型实例之烧开水

  从一个烧开水的例子出发。现在我们有个热水器,我们用它来烧开水。在烧水的过程中,显示器和扬声器都一直监视水温。显示器将水温显示在显示屏上。另外,当水温超过90度时,扬声器开始发出警告,提示水快烧开。

Java实现

  Java对观察者类的支持,主要体现在Observable类和Observer接口。

1. java.util.Observable类 = 被观察者

Observable类的主要方法:

public class Observable {
void setChanged(); //设置被观察者的状态已经被改变
void clearChanged(); //清除被观察者状态的改变,此时再调用hasChanged()将返回false
void addObserver(Observer observer);
int countObservers();
void deleteObserver(Observer observer);
void deleteObservers();
boolean hasChanged();
void notifyObservers();
void notifyObservers(Object arg); // 参数一般设定为被改变的属性
}

热水器类继承自Observerable类,作为一种具体的被监控对象:

public class Heater extends Observable {
private int temperature; // get方法,返回水温
public int getTemperature(){
return temperature;
} // set方法,设置水温
public void setTemperature(int temperature){
this.temperature = temperature;
} // boilWater方法,烧水
public void boilWater(){
for(int i = 30; i <= 100; i++){
this.setTemperature(i);
this.setChanged();
this.notifyObservers(this.getTemperature());
this.clearChanged();
}
}
}

2. java.util.Observer接口 = 观察者

  Observer接口只有一个抽象方法需要被具体的观察者实现。

public interface Observer{
void update(Observable observable, Object arg); //这里的arg即Obserbale类里的notifyObservers(Object arg)传过来的参数
}

  Note:当被观察者调用nofityObservers(*)方法时,会根据被观察者的hasChanged()方法来判断它的状态是否被改变。如果改变,则观察者调用update方法。否则不调用(即不更新)。

  显示器和扬声器作为具体的热水器水温监视者,都需要实现Observer接口。对于显示器,它的update方法作用就是更新显示的水温。对扬声器,它的update方法则是在水温超过90度时发出警告。具体代码如下:

// 显示器
public class Displayer implements Observer {
public void update(Observable observable, Object arg){
display((int)arg);
}
  
public void display(int temperature){
System.out.println("Current Temperature is: " + temperature + " degree.");
}
} // 扬声器
public class Alertor implements Observer {
public void update(Observable observable, Object arg){
int temperature = (int) arg;
if(temperature > 90){
alarm();
}
} public void alarm(){
System.out.println("Warning: Temperature is over 90 degree!" );
}
}

3. 测试类

public class TestObserver{
public static void main(String[] args){
// 生成设备
Heater heater = new Heater();
Displayer displayer = new Displayer();
Alertor alertor = new Alertor(); // 添加订阅 - 重点(!!!)
heater.addObserver(display);
heater.addObserver(alertor); // 烧水
heater.boilWater();
}
}

4. 将上面的3个步骤统一起来,写到一个文件中如下:文件名TestObserver.java

import java.util.Observable;
import java.util.Observer; public class TestObserver {
public static void main(String[] args){
// 生成设备
Heater heater = new Heater();
Displayer displayer = new Displayer();
Alertor alertor = new Alertor(); // 添加订阅
heater.addObserver(displayer);
heater.addObserver(alertor); // 烧水
heater.boilWater();
}
} class Heater extends Observable {
private int temperature; // get方法,返回水温
public int getTemperature(){
return temperature;
} // set方法,设置水温
public void setTemperature(int temperature){
this.temperature = temperature;
} // boilWater方法,烧水
public void boilWater(){
for(int i = 30; i <= 100; i++){
this.setTemperature(i);
this.setChanged();
this.notifyObservers(this.getTemperature()); // 只需传入监视器感兴趣的变量
this.clearChanged();
}
}
} // 显示器
class Displayer implements Observer {
public void update(Observable observable, Object arg){
display((int)arg);
}
  
public void display(int temperature){
System.out.println("Displayer: Current Temperature is: " + temperature + " degree.");
}
} // 扬声器
class Alertor implements Observer {
public void update(Observable observable, Object arg){
int temperature = (int) arg;
if(temperature > 90){
alarm();
}
} public void alarm(){
System.out.println("Alertor: Warning: Temperature is over 90 degree!" );
}
}

最后的输出结果为:

Displayer: Current Temperature is:  30  degree.
Displayer: Current Temperature is: 31 degree.
Displayer: Current Temperature is: 32 degree.
...
Displayer: Current Temperature is: 90 degree.
Displayer: Current Temperature is: 91 degree.
Alertor: Warning: Temperature is over 90 degree!
Displayer: Current Temperature is: 92 degree.
Alertor: Warning: Temperature is over 90 degree!
...
Displayer: Current Temperature is: 99 degree.
Alertor: Warning: Temperature is over 90 degree!
Displayer: Current Temperature is: 100 degree.
Alertor: Warning: Temperature is over 90 degree!

总结

第一次写技术博客感觉比较费劲。原以为一个下午能把三种实现方法都写完的,结果只写完了Java部分。后续的Objective-C 和C#部分计划明天下午搞定。敬请期待。

欢迎交流和讨论^_^ ~ 如有任何问题,请发送到邮箱:fengfu0527@gmail.com

[1]. 《Design Patterns: Elements of Reusable Object-Oriented Software》

[2]. Java之美之设计模式,链接:http://bolg.csdn.net/zhangerqing/article/details/8194653

[3]. 《Java与模式》

 

设计模式之观察者模式(Java)的更多相关文章

  1. 设计模式01观察者模式(java)

    先发代码,有空来写内容. observer1 import java.util.Observer; import java.util.Observable; //学生类(Student)继承Obser ...

  2. 折腾Java设计模式之观察者模式

    观察者模式 Define a one-to-many dependency between objects where a state change in one object results in ...

  3. 设计模式之第18章-观察者模式(Java实现)

    设计模式之第18章-观察者模式(Java实现) 话说曾小贤,也就是陈赫这些天有些火,那么这些明星最怕的,同样最喜欢的是什么呢?没错,就是狗仔队.英文的名字比较有意思,是paparazzo,这一说法据说 ...

  4. 23种设计模式全解析 (java版本)

    转自:http://blog.csdn.net/longyulu/article/details/9159589 其中PHP常用的五种设计模式分别为:工厂模式,单例模式,观察者模式,策略模式,命令模式 ...

  5. java_设计模式_观察者模式_Observer Pattern(2016-07-27)

    看了好几篇文章,最终还是觉得<Head First 设计模式>举得例子比较符合观察者模式. 观察者模式概述: 观察者模式有时被称作发布/订阅模式,它定义了一种一对多的依赖关系,让多个观察者 ...

  6. 设计模式之观察者模式(Observable与Observer)

    设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...

  7. Head First 设计模式之观察者模式(Observer Pattern)

    前言: 这一节开始学习观察者模式,开始讲之前会先像第一节那样通过一个应用场景来引入该模式.具体场景为:气象站提供了一个WeatherData对象,该对象可以追踪获取天气的温度.气压.湿度信息,Weat ...

  8. 从设计模式说起JAVA I/O流

    从设计模式说起JAVA I/O流 之前写过一篇I/O流的入门介绍,直到最近看了设计模式,顺带理下I/O流的设计思路. JAVA类库中的I/O类分成输入和输出两部分,通过继承,任何自InputStrea ...

  9. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  10. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

随机推荐

  1. sql server保留小数解决方法

    在数据库中,我们有时会用到小数,怎样在数据库中转化小数呢,下面是一些常用的方法. 1.使用Round(字段名/数字,小数保留位数)方法,如下所示: select Round(3.333,2) 结果如下 ...

  2. LAMP介绍及安装

    LAMP介绍及安装 1. LAMP是什么? LAMP,包含Linux + Apache + PHP + Mysql. LAMP适用环境 适用于追求极致稳定的WEB环境,缺点是需要消耗更多资源. 除了L ...

  3. WEB标准:标准定义、好处、名词解释、常用术语、命名习惯、浏览器兼容、代码书写规范

    1. WEB标准是什么? “WEB标准”是一系列标准的总称.一般的误区经常把WEB标准说成DIV+CSS.准确的说法应该是:采用W3C推荐的WEB标准中的XHTML1.1结合CSS2.0 样式表制作页 ...

  4. weblogic启动时报错 java.lang.OutOfMemoryError: PermGen space

    PermGen space的全称是Permanent Generation space,是指内存的永久保存区域.这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入Perm ...

  5. Chapter 02:复合 VS 继承

    复合优先于继承,继承是实现代码重用的有力手段,并不是所有情况都适用,使用不当会导致软件变得很脆弱.与方法调用不同的是,继承打破了封装性. 总而言之,组合和继承,都能实现对类的扩展.但是要分具体情况用哪 ...

  6. mysql的四种隔离级别

    一.READ UNCOMMITTED(未提交读) 在READ UNCOMMITTED级别,事务中的修改,即使未提交,对其他事务也都是可见的.事务可以读取未提交的数据,这也被称为脏读( Dirty RE ...

  7. ~/microwindows-0.89pre8/src/bin$ ./nano-X error:Cannot bind to named socket

    GUI:microwindows-0.89pre8+nona-X you are successful compiling, run nano-X,below is information: ~/mi ...

  8. python核心编程-第四章-个人笔记

    1.所有的python对象都拥有三个特性: ①身份:每个对象都有唯一的身份标识自己,可用内建函数id()来得到.基本不会用到,不用太关心 >>> a = 2 >>> ...

  9. C语言基础06

    函数: 一组特定功能的代码段,之所以使用函数,为了在文件多处需要同一段代码时可以多次重复利用,减少代码冗余. //函数的声明 返回值类型 函数名称 ( 数据类型 形参1,数据类型 ,形参2 ) ; / ...

  10. Div+Css(一)必备知识

    我只积累我不知道的 参考链接 http://www.kwstu.com/ArticleView/divcss_201442291125960 http://www.kwstu.com/ArticleV ...