java设计模式——观察者模式(Observer Pattern)

原创 2016年08月29日 15:25:06
概述:
       观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。

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

结构:
  • Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。
  • ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
  • Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。
  • ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的addObserver()方法将自己添加到目标类的集合中或通过deleteObserver()方法将自己从目标类的集合中删除。

UML图:


场景:在平时生活中有很多场景都有观察者模式的影子,比如商城宣传、街头艺人、马路交通信号灯等等,这里就举一个过马路的例子,一般十字路口都会有红绿灯,不管行人还是车辆都要根据交通信号灯的信号来确定什么时候过马路,红灯停、绿灯行,这是小学都学过的交通规则了,当然不守交通规则的sb不算。这里的交通信号灯就相当于目标(被观察者),行人或者司机属于观察者。

代码分析:
/**
 * Created by **
 * 目标抽象类
 */
public abstract class Subject {
    private ArrayList<Observer> observers new ArrayList<Observer>();

    /**
     * 增加观察者
     @param observer
     */
    public void addObserver(Observer observer){
        observers.add(observer);
    }

    /**
     * 移除观察者
     @param observer
     */
    public void deleteObserver(Observer observer){
        observers.remove(observer);
    }

    /**
     * 向观察者发出通知
     @param string
     */
    public void notifyObservers(String string){
        for (Observer observer : observers) {
            observer.update(string);
        }
    }
}

/**
 * Created by **
 * 交通信号灯:具体目标
 */
public class TrafficLight extends Subject {
    /**
     * 显示红灯
     */
    public void showRedLight(){
        LogFactory.log("红灯亮了");
        super.notifyObservers("red");
    }
    /**
     * 显示绿灯
     */
    public void showGreenLight(){
        LogFactory.log("绿灯亮了");
        super.notifyObservers("green");
    }
}

/**
 * Created by **
 * 观察者接口
 */
public interface Observer {
    // 更新操作
    public void update(String string);
}

/**
 * Created by **
 * 司机:观察者
 */
public class Driver implements Observer {
    @Override
    public void update(String string) {
        LogFactory.log("E lights :"+string);
        if ("red".equals(string)){
            stop();
        }else if ("green".equals(string)){
            travel();
        }else {
            LogFactory.log("交通信号灯坏了?...");
        }
    }

    private void travel(){
        LogFactory.log("绿灯亮了,可以过马路了");
    }

    private void stop(){
        LogFactory.log("红灯亮了,停止前行");
    }
}

客户端调用:
TrafficLight trafficLight = new TrafficLight();

Driver driver = new Driver();

trafficLight.addObserver(driver);

trafficLight.showGreenLight();

try {
    Thread.sleep(2000);
    trafficLight.showRedLight();
catch (InterruptedException e) {
    e.printStackTrace();
}

log输出:
08-19 15:14:41.842 2648-2648/? D/test: 绿灯亮了
08-19 15:14:41.842 2648-2648/? D/test: E lights :green
08-19 15:14:41.842 2648-2648/? D/test: 绿灯亮了,可以过马路了
08-19 15:14:43.842 2648-2648/? D/test: 红灯亮了
08-19 15:14:43.842 2648-2648/? D/test: E lights :red
08-19 15:14:43.842 2648-2648/? D/test: 红灯亮了,停止前行

      上述例子,我只是添加了一个观察者,如果要添加多个观察者直接调用addObserver方法即可,另外观察者模式在java语言中的地位非常重要所以jdk里边提供了相关的接口来支持该模式。

JDK提供的Observable类及Observer接口:
  • Observer接口:相当于观察者接口。该接口只声明一个方法:update(Observable observable, Object data)。
  • Observable类:相当于目标抽象类(Subject)。该抽象类中有多个方法:
          
下面将上述代码做一下修改,将具体的目标类继承Observable,将具体的观察者类实现Observer接口:
/**
 * Created by **
 * 交通信号灯:具体目标
 */
public class TrafficLight extends Observable {
    /**
     * 显示红灯
     */
    public void showRedLight(){
        LogFactory.log("红灯亮了");
        super.setChanged();
        super.notifyObservers("red");
    }
    /**
     * 显示绿灯
     */
    public void showGreenLight(){
        LogFactory.log("绿灯亮了");
        super.setChanged();
        super.notifyObservers("green");
    }
}

/**
 * Created by **
 * 司机:观察者
 */
public class Driver implements Observer {
    /*@Override
    public void update(String string) {
        LogFactory.log("E lights :"+string);
        if ("red".equals(string)){
            stop();
        }else if ("green".equals(string)){
            travel();
        }else {
            LogFactory.log("交通信号灯坏了?...");
        }
    }*/
    @Override
    public void update(Observable observable, Object data) {
        LogFactory.log("E lights :"+data);
        if ("red".equals(data.toString())){
            stop();
        }else if ("green".equals(data.toString())){
            travel();
        }else {
            LogFactory.log("交通信号灯坏了?...");
        }
    }
    private void travel(){
        LogFactory.log("绿灯亮了,可以过马路了");
    }

    private void stop(){
        LogFactory.log("红灯亮了,停止前行");
    }

}

客户端的代码不需要更改,最后log输出都是一样一样的,你们可以自己验证一下。

优点:
  • 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
  • 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
  • 观察者模式支持广播通信。
  • 观察者模式符合“开闭原则”的要求。

缺点:
  • 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

适用环境:
  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

扩展:
      MVC模式是一种架构模式,它包含三个角色:模型(Model),视图(View)和控制器(Controller)。观察者模式可以用来实现MVC模式,观察者模式中的观察目标就是MVC模式中的模型(Model),而观察者就是MVC中的视图(View),控制器(Controller)充当两者之间的中介者(Mediator)。当模型层的数据发生改变时,视图层将自动改变其显示内容。


设计模式笔记——(三:观察者模式 Observer Pattern)

观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/...
  • xiaoyu_93
  • xiaoyu_93
  • 2016年11月18日 15:38
  • 822

设计模式总结之Observer Pattern(观察者模式)

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。...
  • cooldragon
  • cooldragon
  • 2016年08月11日 00:53
  • 850

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

观察者模式(Observer Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权...
  • u012515223
  • u012515223
  • 2014年05月22日 14:37
  • 2915

设计模式之观察者模式 (Observer Design Pattern)

一、什么是观察者模式观察者定义了一种一对多的依赖关系,当一个主题(Subject)对象状态发生变化时,所有依赖它的相关对象都会得到通知并且能够自动更新自己的状态,这些依赖的对象称之为观察者(Obser...
  • suifeng3051
  • suifeng3051
  • 2016年04月27日 19:32
  • 902

Observer 模式及JAVA内置的observer示例

关于观察者模式 假设今天您设计一个图形分析算表程序,当中有一个资料物件,您可以用表格图形物件、柱状图形物件、圆饼图形物件等方式来 呈现物件,无论您是用哪种图形物件,重点是若资料物件的内容作了更改,则图...
  • hu1020935219
  • hu1020935219
  • 2014年09月22日 12:42
  • 2313

Java观察者模式(Observer)详解及应用

Java的设计模式很多,观察者模式被称为是模式中的皇后,而且Java jdk也对它做了实现,可见该设计模式的重要位置。在图形化设计的软件中,为了实现视图和事件处理的分离,大多都采用了Observer模...
  • u014657292
  • u014657292
  • 2014年04月21日 10:23
  • 1657

Java:应用Observer接口实践Observer模式

转自:http://zhangjunhd.blog.51cto.com/113473/68949/  在Java中通过Observable类和Observer接口实现了观察者模式。Obser...
  • hgsunyong
  • hgsunyong
  • 2015年01月28日 09:46
  • 681

Java 实现观察者(Observer)模式

1. Java自带的实现 类图 /** * 观察目标 继承自 java.util.Observable * @author stone * */ public class UpdateOb...
  • jjwwmlp456
  • jjwwmlp456
  • 2014年10月10日 19:11
  • 2259

Java之观察者模式(Observer Pattern)

观察者模式用来对GUI中的动作做侦听。Swing GUI的例子就表明了动作侦听是怎样实现观察者模式的。 下面是一个猎头的典型例子。这个图中有2个角色-猎头和求职者。求职者先在猎头处注册,当有新的...
  • weifanyite505
  • weifanyite505
  • 2015年08月20日 15:03
  • 231

观察者模式(Observer) Java

定义  观察者模式(Observer 发布-订阅):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 ...
  • dingsai88
  • dingsai88
  • 2016年06月18日 16:12
  • 2059
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java设计模式——观察者模式(Observer Pattern)
举报原因:
原因补充:

(最多只允许输入30个字)