《设计模式》学习笔记7——观察者模式

标签: 设计模式 观察者模式
177人阅读 评论(2) 收藏 举报
分类:

定义

观察者模式是使用频率最高的设计模式之一,也是最容易理解的设计模式之一,这种模式在生活中随处可见。
观察者模式引用书中的定义如下:

观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(PublishSubscribe) 模式、模型-视图(Model/View) 模式、源-监听器(Source/Listener)模式或从属者(Dependents) 模式。观察者模式是一种对象行为型模式

理解

观察者模式在生活中随处可见,路口的红绿灯和行人及车辆的关系是一种观察者模式,演员和观众是一种观察者模式,甚至于一个人说话,其他人听,也是一种观察者模式。
说白了,就是一个对象发出了某种信号,其他对象会根据这个对象立即作出某些动作或反应(什么也不做也是一种动作和反应)。
根据理解,我写了一个新闻网站根据中央气象台气象信息更新各自网站主页天气信息的小例子。

被观察者

在这里,中央气象台充当被观察者,各大网站充当观察者,首先我们定义一个被观察者的接口(但从实现观察者模式来说可以不用接口,但为了更好的拓展,这里使用接口编程)。

package patterntest.observerpattern.subject;
import java.util.ArrayList;
import java.util.List;
import patterntest.observerpattern.observer.WebSite;

/**
 * 气象台接口
 * 
 * @author tzx
 * @date 2017年12月5日
 */
public interface MyObservatory {
    /*
     * 存放观察者集合
     */
    List weblist = new ArrayList();

    /**
     * 增加新观察者
     * 
     * @param webSite
     */
    public void addWebSite(WebSite webSite);

    /**
     * 删除观察者
     * 
     * @param webSite
     */
    public void removeWebSite(WebSite webSite);

    /**
     * 发布天气信息
     */
    public void pubMsg();

}

在这个接口中有几个必要因素:
1. 保存所有观察者对象的集合
2. 新增观察者对象的方法
3. 删除观察者对象的方法
4. 发布信息的方法,也称为通知观察者的方法

然后写一个实现上述接口的实现类,把抽象方法实现:

package patterntest.observerpattern.subject;
import patterntest.observerpattern.observer.WebSite;
public class WeatherObservatory implements MyObservatory {

    @Override
    public void addWebSite(WebSite webSite) {
        weblist.add(webSite);

    }

    @Override
    public void removeWebSite(WebSite webSite) {
        weblist.remove(webSite);

    }

    @Override
    public void pubMsg() {
        for (WebSite webSite : weblist) {
            webSite.update();
        }

    }

}

add和remove方法应该不需要多说,就是向list集合加元素和删元素。重点在于pubMsg方法,也就是这里的发布天气信息的方法,这是观察者模式的核心所在。
在这个方法中,会遍历保存着所有观察者对象的集合,然后调用每个观察者对象的具体行为方法。当然了,这里边的逻辑可以自定义,未必就是通知所有观察者。

观察者

有了被观察者,接下来就是创建观察者,在上边的pubMsg方法中,我们调用了WebSite对象的update方法,但是现在还没有定义相应的对象。
观察者模式一般是一对多的关系,虽然说实际一对一也是没问题的,但是似乎就有些大材小用了。所以我们这里的观察者就使用多对象,这些对象都是观察者,所以有一个共同的父类:观察者接口。

package patterntest.observerpattern.observer;

/**
 * 观察者:网站接口
 * 
 * @author tzx
 * @date 2017年12月5日
 */
public interface WebSite {
    /**
     * 根据观察到的信息采取行动
     */
    public void update();
}

可以看到观察者接口的定义相对于被观察者就简单多了,只有一个update方法,也就是观察到被观察对象的状态变化后采取的行动。
观察者是一个抽象的说法,就需要有更具体的观察者,相对于这里的网站接口,我就给他两个观察者子类:新浪网和腾讯网。

package patterntest.observerpattern.observer;

public class Sina implements WebSite {

    @Override
    public void update() {
        System.out.println("新浪天气更新");
    }

}
package patterntest.observerpattern.observer;

public class Tencent implements WebSite {

    @Override
    public void update() {
        System.out.println("腾讯天气更新");
    }

}

上边两个观察者做的事太过于简单,所以就不多说了。接下来就模拟新浪网、腾讯网相继开始观察中央气象台的天气信息,然后中央气象台发布新的气象并通知两大网站。

import patterntest.observerpattern.observer.Sina;
import patterntest.observerpattern.observer.Tencent;
import patterntest.observerpattern.observer.WebSite;
import patterntest.observerpattern.subject.MyObservatory;
import patterntest.observerpattern.subject.WeatherObservatory;
import patterntest.observerpattern.subject.WindObservatory;

/**
 * 观察者模式测试
 * 
 * @author tzx
 * @date 2017年12月5日
 */
public class ObserverTest {

    public static void main(String[] args) {
        // 建立中央气象台
        MyObservatory observatory = new WeatherObservatory();
        // 创建新浪网
        WebSite sina = new Sina();
        // 新浪网开始观察中央气象台信息公告
        observatory.addWebSite(sina);
        // 创建腾讯网
        WebSite tencent = new Tencent();
        // 腾讯网开始观察中央气象台信息公告
        observatory.addWebSite(tencent);
        // 中央气象台发布新的天气信息
        int i = 0;
        do {
        observatory.pubMsg();
            i++;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } while (i 

要点

根据上边的实例和分析,观察者模式包含如下一些要点:
1. 需要一个被观察者,也称作观察目标
2. 观察目标中需要有一个保存所有观察者对象的集合
3. 观察目标中需要有增加观察者对象的方法
4. 观察目标中需要有删除观察者对象的方法
5. 观察目标中需要有发布信息,也称作通知观察者对象的方法
6. 观察者需要有一个提供给被观察者的方法

由上边总结的一些要点,应该很容易就写出一个观察者模式了,但是在观察者模式中还有一些需要特别说明的地方:
1. java提供了对观察者模式的支持,java.util包中有关于观察者模式的两个接口Observer和Observable。所以要写一个观察目标的类,可以实现Observable接口;要写一个观察者的类,可以实现Observer接口。
2. 观察者模式的实现逻辑上,可能与现实中的某些理解稍有差异。就如上边气象台的例子,原则上来说,气象台并不知道有哪些网站在观察气象信息,网站更新天气信息的主动权在网站手上。但是在代码实现观察者模式的时候,却是由观察目标来通知观察者的,观察目标那里需要保存所有观察者对象。

总结

观察者模式不论是理解还是具体实现都比较简单,可能也是因为简单,所以生活中随处可见,也可能是因为生活中随处可见,所以理解起来才显得简单。
观察者模式中保存了所有观察者对象,当使用抽象编程的时候,只需要维护一个观察者父类的集合,这样以后有了新的观察者,也不用改变观察目标,实现了一定程度的松耦合。
但是从上边示例中就可以看到,通知观察者的方法会遍历观察者对象集合,然后依次调用每个观察者对象的相应方法。所以如果这个观察者集合非常大,观察者非常多,或者相应的方法并不能很快结束。则必然影响整体的效率,也会出现数据延迟的问题。
同时,虽然可以通过参数传递的方式使观察者知道观察目标的状态,却无法知道观察目标的具体状态具体是如何变化的。

demo源码可在github下载:https://github.com/tuzongxun/mypattern

查看评论

设计模式(五)观察者模式

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听莫一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们...
  • itachi85
  • itachi85
  • 2016-03-02 17:41:50
  • 43538

Java设计模式-回调函数和观察者模式

Android的框架中有非常多的地方使用了回调的模式,例如Activity的生命周期,按钮的点击事件等。 下面是回调的基本模型: public class A { private CallBack...
  • cauchyweierstrass
  • cauchyweierstrass
  • 2015-03-24 16:20:44
  • 9369

大话设计模式—观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。主要解决一个对象状态改变给其他对象通知的问...
  • lmb55
  • lmb55
  • 2016-03-27 22:57:41
  • 1125

JAVA设计模式(二)工厂模式与观察者模式

工厂模式   工厂模式顾名思义则是类似于一个工厂制造产品的模式。如富士康需要制造自己的产品,而同类产品有多种,如手机有各个品牌和型号一样。   明白了工厂模式的含义,我们来想想这个模式具体是怎么回...
  • hukuhy
  • hukuhy
  • 2016-12-10 10:52:14
  • 866

最常用的设计模式---观察者模式(C++实现)

最常用的设计模式---装饰者模式(C++实现)
  • lh844386434
  • lh844386434
  • 2014-01-08 17:55:01
  • 3224

Android设计模式(十一)-观察者模式

观察者模式是一种使用频率非常高的设计模式,最常用的地方就是订阅-发布系统。这个模式的重要作用就是将观察者和被观察者解耦,使他们之间的依赖更小甚至没有。定义定义对象一种一对多的依赖关系,使得每当一个对象...
  • qq_25806863
  • qq_25806863
  • 2017-04-05 00:26:48
  • 1405

Java设计模式(观察者模式JDK自带)

JDK自带的观察者模式和我们上一节说的基本相似,也有通用的观察协议规则 Observer,这个接口中只有一个方法,就是update方法 public interface Observer { ...
  • xyjwsj
  • xyjwsj
  • 2017-02-15 16:47:03
  • 903

设计模式:观察者模式java和javabean

观察者编程思路:        1.初始化被观察者         2.被观察者中添加观察者         3.设置属性值         4.setChanged方法通知change为true ...
  • stonehigher125
  • stonehigher125
  • 2013-12-06 11:54:54
  • 685

设计模式 观察者模式 以微信公众服务为例

继续设计模式的文章,今天给大家带来观察者模式。 先来看看观察者模式的定义: 定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。 好了,对于定义的理解总是...
  • lmj623565791
  • lmj623565791
  • 2014-04-20 13:27:32
  • 20841

C#设计模式---观察者模式简单例子

在开发过程中经常遇到一个模块中的 一个方法调用了其他模块中相关的方法 比如说在一个系统中,如果出现了错误,就调用专门进行错误处理的模块中的方法进行错误处理 而因为错误处理的操作有很多,所以将这些具...
  • qq1010885678
  • qq1010885678
  • 2014-07-27 11:44:38
  • 2154
    公告栏
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 89万+
    积分: 1万+
    排名: 1864