观察者(Observer)模式

  观察者模式又叫做发布-订阅模式(Publish.Subscribe)模式、模型-视图模式(Model/View)模式、源-监听器模式(Source/Listener)模式或从属者(Dependents)模式。

  观察者模式定义了一种一对多的依赖关系,让多个观察者同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

1.  观察者模式结构

一个简单的观察者模型如下:

角色:

抽象(Subject)主题角色:把所有的观察者维持在一个集合中,每个主题都可以有任意数量的观察者。提供一个接口,可以增加和删除观察者,主题角色又叫做被观察者(Observable)。

抽象观察者(Observer)角色:在得到主题的通知时更新自己。有时候观察者依赖于被观察者,可以将update方法修改为 void update(Subject subject)。

具体主题角色:维护所有的观察者,在具体主题的内部状态改变时给所有登记的观察者发送通知。

具体观察者角色:存储与主题的状态自恰的状态,也就是随着主题的状态改变自己的状态。

代码如下:

package cn.qlq.observer;

public interface Subject {
    void attach(Observer observer);

    void delete(Observer observer);

    void notifyObservers();
}
package cn.qlq.observer;

import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

public class ConcreteSubject implements Subject {

    private List<Observer> observers = new Vector<>();

    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void delete(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

}
package cn.qlq.observer;

public interface Observer {

    /**
     *
     */
    void update();

}
package cn.qlq.observer;

public class ConcreteObserver implements Observer {

    @Override
    public void update() {
        System.out.println(" i am notified");
    }

}

2.  第二种实现

  考虑上面的主题中,管理维护观察者集合的方法可以放到抽象类中去实现,因此可以将维护观察者关系的代码抽取到抽象类中,类图如下:

  这种方式与上面的区别是代表存储观察者对象的集合从连线是从抽象主题到抽象观察者。(也就是抽象主体维护抽象观察者的引用关系)

代码如下:

package cn.qlq.observer;

import java.util.List;
import java.util.Vector;

public abstract class Subject {
    private List<Observer> observers = new Vector<>();

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void delete(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}
package cn.qlq.observer;

public class ConcreteSubject extends Subject {

    private String state;

    public void changeState(String newState) {
        state = newState;
        this.notifyObservers();
    }

}
package cn.qlq.observer;

public interface Observer {

    /**
     *
     */
    void update();

}
package cn.qlq.observer;

public class ConcreteObserver implements Observer {

    @Override
    public void update() {
        System.out.println(" i am notified");
    }

}

客户端测试代码:

package cn.qlq.observer;

public class Client {

    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        Observer observer = new ConcreteObserver();

        subject.attach(observer);

        subject.changeState("1");
    }

}

3.  Java语言对观察者模式的支持

  在Java.util保重中,提供了一个Observable类以及一个Observer接口。

Observer接口:  此接口只定义了一个update方法,当被观察者的状态发生变化时被观察者对象的notifyOeservers()方法会调用这一方法。

public interface Observer {

    void update(Observable o, Object arg);
}

Observable类:被观察者类都是该类的子类,该类有两个重要的方法:

  setChanged():  设置一个内部标记标记其状态发生变化

  notifyObsers(): 这个方法被调用时会调用所有注册的观察者的update()方法。

package java.util;

public class Observable {
    private boolean changed = false;
    private Vector obs;

    public Observable() {
        obs = new Vector();
    }
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}

简单的使用Java对观察者模式的支持:

package cn.qlq.observer;

import java.util.Observable;

public class Watched extends Observable {

    private String data = "";

    public String getData() {
        return data;
    }

    public void changeData(String data) {
        if (!this.data.equals(data)) {
            this.data = data;
            setChanged();
        }

        notifyObservers();
    }

}
package cn.qlq.observer;

import java.util.Observable;
import java.util.Observer;

public class Watcher implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        if (o != null && (o instanceof Watched)) {
            Watched watched = (Watched) o;
            System.out.println("data changed to: " + watched.getData());
        }
    }

}

客户端代码

package cn.qlq.observer;

public class Client {

    public static void main(String[] args) {
        Watched watched = new Watched();
        Watcher watcher = new Watcher();

        watched.addObserver(watcher);

        watched.changeData("123");
        watched.changeData("123");
        watched.changeData("456");
        watched.changeData("789");
    }
}

结果:(虽然改变了四次值,但是有两次一样,查看源码啊在notifyObsers()中会清掉changed的值)

data changed to: 123
data changed to: 456
data changed to: 789

4.  观察者模式优缺点

优点:

(1)观察者模式在被观察者和观察者直接建立一个抽象的耦合

(2)观察者模式支持广播通信。被观察者会向所有登记的观察者发出通知。

缺点:

(1)如果被观察者的观察者过多,通知所有观察者需要花费很多时间

(2)如果在被观察者之间有循环依赖容易循环调用

(3)如果对观察者的通知是通过多线程通知必须保证通知的正确性

(4)观察者可以知道观察者状态发生了变化,不知道是怎么发生变化的。

原文地址:https://www.cnblogs.com/qlqwjy/p/11324341.html

时间: 2024-11-05 11:44:13

观察者(Observer)模式的相关文章

Android 适配器(Adapter)、观察者(Observer) 模式

适配器(Adapter)详述:http://blog.csdn.net/jjwwmlp456/article/details/39893723 观察者(Observer)详述:http://blog.csdn.net/jjwwmlp456/article/details/39967021 AdapterView 体系 AdapterView中会使用Adapter Adapter 体系 BaseAdapter 实现了 SpinnerAdapter.ListAdapter 这样的形式,就是 适配器模

Java 实现观察者(Observer)模式

1. Java自带的实现 类图 /** * 观察目标 继承自 java.util.Observable * @author stone * */ public class UpdateObservable extends Observable { private int data; public UpdateObservable(Observer observer) { addObserver(observer); /* * add other observer */ } public int

C++ 实现观察者(Observer)模式详解

观察者(Observer)模式,是常见的模式之一.比如一份报纸,有很多订户.订阅者并不知道报纸何时会送来,他只知道自己订了这份报纸.订阅者在这里担任着观察者的角色,而报社则是被观察者. 报纸一旦印刷完毕,就应该及时送到订户手中,如果将报社看作一个对象,则报纸便是观察者(订户)和被观察者(报社)之间的纽带.观察者需要维护一个与报纸相关的变量或函数,在这个具体问题中,这个变量就是订户是否收到报纸,可设置为一个布尔型,当收到时,订户需要更新这个变量. 下面是源码: // "Observer.H&quo

【设计模式】HeadFirst设计模式(二):观察者(Observer)模式

一.观察者模式定义 在观察者模式中,一个被观察者管理所有依赖于它的观察者对象,它定义了一个一对多的依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新. 主题(被观察者)通过一个共同的接口来更新观察者,观察者依赖于此主题. 二.观察者模式例子--气象监测系统 描述: 气象监测系统分为三个部分:气象站(获取实际气象数据的物理装置).WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看) 布告板分为三个:目前状况(显示Weath

Android与设计模式——观察者(Observer)模式

在阎宏博士的<JAVA与模式>一书中开头是这样描述观察者(Observer)模式的: 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式.源-监听器(Source/Listener)模式或从属者(Dependents)模式. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 观察者模式的结构 一个软件系统里面包含了

Observer(观察者)模式

1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来说,当某个对象的状态发生改变时,你仍然需要对象之间能互相通信.但是出于各种原因,你也许并不愿意因为代码环境的改变而对代码做大的修改.也许,你只想根据你的具体应用环境而改进通信代码.或者,你只想简单的重新构造通信代码来避免类和类之间的相互依赖与相互从属. 2.问题 当一个对象的状态发生改变时,你如何通知其他对象?是否需要一个动态方案――一个就像允许脚本的执行一样,允

【行为型】Observer模式

观察者模式意图解决一对多的依赖关系情形中,当被依赖对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新的问题.举个很简单的例子说,假如一个游戏中的角色的某个属性状态发生了变化,此处不妨假设为角色的等级升级了,则相应的在游戏场景中的模型展现([依赖点1])需要跟着调整,并且在UI界面上的角色属性([依赖点2])描述细节中还需要及时更新成新等级值展现给玩家.这边的[依赖点1]与[依赖点2]就依赖于角色的属性,并且对于这两个依赖点来说,属性对它们都是很敏感的,它们需要能够及时感知到这些属性的

用java.util.Observable实现Observer模式

本文转载自:dada360778512的博客 原文链接:http://blog.csdn.net/dada360778512/article/details/6977758 Observer模式  主要是观察者与被观察者之间的关系 观察者为羊,被观察者为狼  模仿的场景为狼叫羊跑 代码如下: 1.被观察者类 [java] view plaincopy package test.pattern.observer; import java.util.Observable; public class 

Observer 模式

Observer模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当"一"变化的时候,依赖这个"一"的多也能够同步改变.最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望 能够提供多种形式的表示 (例如以表格进行统计显示. 柱状图统计显示. 百分比统计显示等) .这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变.Observer模式就是解决了这一个问题. 1 ////////