设计模式(二)The Observer Pattern 观察者模式

问题引入

生成一个公告板显示当时的天气状况,当天气状况发生改变的时候公告板能够实时的更新。

模式定义

定义对象之间的一对多的依赖。当一个对象改变状态时,它的全部依赖者都会自己主动收到通知并自己主动更新。

认识模式

该模式在生活中是非经常见的。想想生活中的各种各样的检測系统,报警系统,一旦有重要事件发生时,有关系统总能及时的收到通知。这就是观察者模式。

问题解决

关于观察者模式,java实际上给了我们内置的支持(能够看出该模式还是非经常常使用的吧!)可是我们经常会自己实现。

为什么呢?我们后面会给出答案。

被观察者我们称之为主题(Subject)。对应的有观察者(Observer)。

一、自己定义实现

1)  Subject,Observer我们都定义为接口

?


1

2

3

4

5

6

7

8

9

10

11

package my.oschina.net.design.observer.owndesign;

public interface Subject {

    public void registerObserver(Observer o);

    public void removeObserver(Observer o);

    public void notifyObserver();    

}

public interface Observer {

    void update(Subject sub);

}

2)实现Subject和Observer接口(主题与观察者的实现)

a)主题实现

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

package my.oschina.net.design.observer.finaldesign;

import java.util.ArrayList;

public class WeatherData implements Subject{

    

    //被观測的指标数据

    private float temp;

    private float humidity;

    private float pressure;

    

    //维护一个订阅过的Observer列表

        private ArrayList<Observer> Observers;

    

    public WeatherData()

    {

        this.Observers = new ArrayList<Observer>();

    }

    @Override

    //添加Observer

    public void registerObserver(Observer o) {

        // TODO Auto-generated method stub

        Observers.add(o);      

    }

    @Override

    //移除部分Observer

    public void removeObserver(Observer o) {

        // TODO Auto-generated method stub

        int i = Observers.indexOf(o);

        if(i != -1)

            Observers.remove(Observers.indexOf(o));    

    }

    

    @Override

    //通知订阅过的Observer

    public void notifyObserver() {

        // TODO Auto-generated method stub

        for(Observer o : Observers)

        {

            o.update(this);

        }

    }

    

    public void setStatus(float temp, float humidity, float pressure)

    {

        this.temp = temp;

        this.humidity = humidity;

        this.pressure = pressure;

        

        statusChanged();

    }

    

    public void statusChanged()

    {

        notifyObserver();

    }

    

    float getTemp()

    {

        return temp;

    }

    

    float getHumidity()

    {

        return humidity;

    }

    

    float getPressure()

    {

        return pressure;

    }  

}

b)观察者实现

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

package my.oschina.net.design.observer.finaldesign;

public class CurrentConditionDisplay implements Observer,Display{

    

    //接收被观測者发过来的数据

    private float temp;

    private float humidity;

    private float pressure;

    //保存这个主题对象,可能兴许有退订的需求

    private WeatherData weatherData;

    

    public CurrentConditionDisplay(WeatherData weahterdata)

    {

        this.weatherData = weahterdata;

        weatherData.registerObserver(this);

    }

    

    @Override

    public void update(Subject sub) {

        // TODO Auto-generated method stub

        

        if(sub instanceof WeatherData)

        {

            WeatherData weatherdata = (WeatherData)sub;

            this.temp = weatherdata.getTemp();

            this.humidity = weatherdata.getHumidity();

            this.pressure = weatherdata.getPressure();

        }

        

        display();

    }

    @Override

    public void display() {

        // TODO Auto-generated method stub

    System.out.println("Temp --> " + temp + "humidity --> " +humidity + "pressure -->" + pressure);

    }

}

3)Test一下

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package my.oschina.net.design.observer.finaldesign;

public class ObserverTest1 {

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        WeatherData weatherdata = new WeatherData();

        

        CurrentConditionDisplay cc = new CurrentConditionDisplay(weatherdata);

        

        weatherdata.setStatus(121212);

        weatherdata.setStatus(131313);

        weatherdata.setStatus(141414);       

    }

}

4)结果截图

二、java内置实现

在java的java.util 包(pac1kage)中包括了最主要的Observable类(可观察,通过继承方式获得其方法和属性)和Observer接口(观察),对你没有看错,我也没有写错,的确是Observable类和Observer接口,他们类似与我们上述自定义的Subject和Observer接口。由于是java内置,有的时候使用它们的话真的是挺简单的,由于有好多的功能java本身已经为我们写好了!

事实上这里你已经能够明确这样的内置实现的弊端了。对就是由于Observable是个类。在java中仅仅支持单继承,所以啊。这就限制了继承他的类使用的灵活性!

java内置的不同

a)关于主题对象

当我们自己定义观察者的时候当须要通知观察者的时候我们直接调用notifyO不servers()方法就可以,
可是java内置的方法不是这种,我们须要两步走:

1>调用setChanged()方法,标记状态已改变。

2>调用notifyObserver()方法,完毕通知的工作。

深入-------->setChanged()

我们来看看Observable内部的实现

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

   setChanged()

   {

       cahnged = true;

   }

  

   notifyObservers(Object arg)

   {

       if(cahnged)

       {

           for every obsrver on the list

           {

               call update(this, arg)

           }

           cahngd = false;

       }

   }

   

    notifyObservers()

    {

        notifyObservers(null)

    }

看到这里有人可能要问了:为什么要设置一个标志呢???细致想想,如果你是公司老总,每天要批一系列文件,好了,如今秘书送来一份文件你批了,一分钟没到,又有新的文件产生了,秘书又送了过来,然后。。。然后。

。。

你受得了吗?你可能会对秘书说:小李啊,这个文件你给我每50份一批给我送过来。我一并审阅!

有时候我们并不希望被观察者有一丝的变化立即就通知我们,我们能够等被观察者达到一定的程度的时候(比方说等温度上升5℃以内不必通知系统。一旦超过5℃就通知系统!)再通知我们。你能够想想这样优点非常多!所以当达到标准,我们须要通知观察者的时候调用setChanged()方法还真是不错的哦!

b)关于观察者

update的方法略有不同update(Observable
o, Object arg),第一个參数是主题本身。第二个參数为传入notifyObserver()的数据对象,没有为空。

这里就来决定是由被观察者push数据。还是有观察者自己pull数据。

代码走起

1)被观察者实现(注意import对应的package)

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

package my.oschina.net.design.observer.javautil;

import java.util.Observable;

import java.util.Observer;

/**

 * 这样的方式有一个弊端就是说Observable是一个 类而不是一个接口因此它限制了这个类的使用

 * @author Eswin

 *

 */

public class WeatherData extends Observable{

    

    //被观測的指标数据

    private float temp;

    private float humidity;

    private float pressure;

    public WeatherData(){}

    

    public void setStatus(float temp, float humidity, float pressure)

    {

        this.temp = temp;

        this.humidity = humidity;

        this.pressure = pressure;

        

        statusChanged();

    }

    

    public void statusChanged()

    {

        setChanged();

        notifyObservers();

    }

    

    public float getTemp()

    {

        return temp;

    }

    

    public float getHumidity()

    {

        return humidity;

    }

    

    public float getPressure()

    {

        return pressure;

    }

    

}

2)观察者实现

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

package my.oschina.net.design.observer.javautil;

import java.util.Observable;

import java.util.Observer;

import my.oschina.net.design.observer.owndesign.Display;

public class CurrentConditionDisplay implements Observer, Display{

    private float temp;

    private float humidity;

    private float pressure;

    

    private Observable observable;

    

    public CurrentConditionDisplay(Observable observable)

    {

        this.observable = observable;

        observable.addObserver(this);

        

    }

    

    @Override

    public void update(Observable o, Object arg) {

        // TODO Auto-generated method stub

        if(o instanceof WeatherData)

        {

            WeatherData weatherdata = (WeatherData)o;

            this.temp = weatherdata.getTemp();

            this.humidity = weatherdata.getHumidity();

            this.pressure = weatherdata.getPressure();

        }

        

        display();

        

    }

    @Override

    public void display() {

        // TODO Auto-generated method stub

        System.out.println("Temp --> " + temp + "humidity --> " +humidity + "pressure -->" + pressure);

    }

}

3)Test一下

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

package my.oschina.net.design.observer.javautil;

public class ObserverTest2 {

    public static void main(String[] args) {

        // TODO Auto-generated method stub     

            WeatherData weatherdata = new WeatherData();

               
    

        CurrentConditionDisplay cc = new CurrentConditionDisplay(weatherdata);

        

        weatherdata.setStatus(121212);

        weatherdata.setStatus(131313);

        weatherdata.setStatus(141414);

    }

}

4)结果截图

模式延伸

事实上我们我们在编程的过程中有非常多时候都运用到了观察者模式,想想Swing。还有JavaBean,还有RMI。

模式建议

1)要注意Observable这个类所带来的问题;

Observable is a class

You already know from our principles this is a bad idea, but what harm does it reallycause?

First, because Observable is a
class, you have to
subclass
it. That means you can’t add

on the Observable behavior to an existing class that already extends another superclass.This limits its reuse potential (and isn’t that why we are using patterns in the first place?).

Second, because there isn’t an Observable interface, you can’t even create your ownimplementation that plays well with Java’s built-in Observer API. Nor do you havethe option of swapping out
the java.util implementation for another (say, a new, multi-threaded implementation).

Observable protects crucial methods

If you look at the Observable API, the setChanged() method is protected. So what?

Well,this means you can’t call setChanged() unless you’ve subclassed Observable. This meansyou can’t even create
an instance of the Observable class and compose it with your ownobjects, you
have to subclass. The design violates a second design principle here...favorcomposition
over inheritance. 

2)有必要的话自己实现Observable也就是主题,非常easy(三个方法实现就能够了)。

安卓中的应用:

观察者模式,是一种非经常见的设计模式。在非常多系统中随处可见。尤其是涉及到数据状态发生变化须要通知的情况下。

本文以AbstractCursor为样例,展开分析。

观察者模式,Observer Pattern,是一个非常有用的模式,本人以前接触到的各种平台以及以前參与项目中打印模板解释器中都用到了此模式。

1.意图

定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时。全部依赖于它的对象都得到通知并被自己主动更新。

热门词汇:依赖 公布-订阅 事件 通知 更新 监听

2.结构

这是一个最简单的观察者模式。目标对象可以加入和删除观察者。当自己某种状态或者行为发生改变时,可通过notify通知注冊的观察者进行更新操作。

分析AbstractCursor的详细情况,我们发现实际工作有时须要对观察者进行统一管理。甚至观察者类型有非常多种而又能够分成几个系列,这个时候是要复杂的多,通过合理的分层这个问题非常好解决。以下依据详细情况,我们画出android中abstractCurosr中用到的观察者模式结构图:

观察者分成了两个系列。

3.代码

列举当中相关核心代码例如以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40


public abstract class AbstractCursor {

//定义管理器

DataSetObservable mDataSetObservable = new DataSetObservable();

ContentObservable mContentObservable = new ContentObservable();

//注冊和卸载两类观察者

public void registerContentObserver(ContentObserver observer) {

mContentObservable.registerObserver(observer);

}

public void unregisterContentObserver(ContentObserver observer) {

// cursor will unregister all observers when it close

if (!mClosed) {

mContentObservable.unregisterObserver(observer);

}

}

public void registerDataSetObserver(DataSetObserver observer) {

mDataSetObservable.registerObserver(observer);

}

public void unregisterDataSetObserver(DataSetObserver observer) {

mDataSetObservable.unregisterObserver(observer);

}

//2类通知方法

protected void onChange(boolean selfChange) {

synchronized (mSelfObserverLock) {

mContentObservable.dispatchChange(selfChange);

if (mNotifyUri != null && selfChange) {

mContentResolver.notifyChange(mNotifyUri, mSelfObserver);

}

}

}

protected void notifyDataSetChange() {

mDataSetObservable.notifyChanged();

}

}

再看看Observable类和DataSetObservable类:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38


public abstract class Observable<T> {

/**

* 观察者列表

*/

protected final ArrayList<T> mObservers = new ArrayList<T>();

public void registerObserver(T observer) {

if (observer == null) {

throw new IllegalArgumentException("The observer is null.");

}

synchronized(mObservers) {

if (mObservers.contains(observer)) {

throw new IllegalStateException("Observer " + observer + "
is already registered.");

}

mObservers.add(observer);

}

}

public void unregisterObserver(T observer) {

if (observer == null) {

throw new IllegalArgumentException("The observer is null.");

}

synchronized(mObservers) {

int index = mObservers.indexOf(observer);

if (index == -1) {

throw new IllegalStateException("Observer " + observer + "
was not registered.");

}

mObservers.remove(index);

}

}

public void unregisterAll() {

synchronized(mObservers) {

mObservers.clear();

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13


public class DataSetObservable extends Observable<DataSetObserver> {

/**

* 数据发生变化时,通知全部的观察者

*/

public void notifyChanged() {

synchronized(mObservers) {

for (DataSetObserver observer : mObservers) {

observer.onChanged();

}

}

}

//... ... (其它方法)

}

 观察者DataSetObserver类是一个抽象类:

1

2

3

4

5


public abstract class DataSetObserver {

public void onChanged() {

// Do nothing

}

}

 所以我们详细看它的子类:

1

2

3

4

5

6

7

8

9

10

11


public class AlphabetIndexer extends DataSetObserver{

/*

* @hide 被android系统隐藏起来了

*/

@Override

public void onChanged() {

//观察到数据变化,观察者做自己该做的事情

super.onChanged();

mAlphaMap.clear();

}

}

 ContentObserver也是类似。

4.效果

  • 行为型模式
  • 目标和观察者间的抽象耦合(经典实现)。
  • 支持广播通信(相信这点android开发人员看到后应该有启示吧)。

  • 注意意外的更新。这也是观察者更新进行管理的原因之中的一个。
时间: 2024-10-17 01:09:49

设计模式(二)The Observer Pattern 观察者模式的相关文章

Head First 之 Design Pattern(二):Observer Pattern

观察者模式是最常用的设计模式之一,[对象之间多对一的依赖关系,当一个对象发生变化时,其会通知所有依赖它的对象].拿订阅报纸和发行报社打比方,报社采集到news制作新的报纸,派送给订阅的客户,以此把最新的消息告知客户.所以,出版社 + 订阅者 = 观察者模式. 这种一对多的关系,也即"一个"主题."多个"观察者能够使得观察者仅仅了解主题推送的消息但不知晓其中的细节,而主题握有观察者列表但不干涉到观察者的个人隐私.所以,它们之间相互有交互,但不紧密,不清楚对方的细节.改

Java设计模式模式观测(Observer Pattern)

Observer Pattern 设计模式通常用于.这是一个事件侦听器模型. 该模型有两个作用,一个是Subject, 有一个Observer.Subject 保存多个Observer参考,一旦一个特定的事件发生.Subject它会通知所有Observer.Observer得到该通知后运行相关程序逻辑. 当中,Observer仅仅有先向Subject注冊后才干被Subject知晓.这就像订报纸,仅仅有我们向出版社提出订报的申请,出版社才会把我们列入订阅者名单.然后每当新报纸印好时,出版社会通知订

设计模式之 Observer Pattern 观察者模式

1.Subject通过一个容器保存零到多个Observer. 2.Subject通过Add,Delete方法调整Observer. 3.Subject的notifyObservers方法实际是逐个调用容器中Observer的notify方法.

c++ 设计模式5 (Observer / Event 观察者模式)

3.3 观察者模式 (Observer)/发布-订阅模式 动机: 在软件构建过程中,我们需要为某些对象建立一种"通知依赖关系"--一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都能得到通知.如果这样的依赖关系过于紧密,将使得软件不能很好地抵御变化. 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系.从而实现软件体系结构的松耦合. 代码示例: 文件分割器,添加处理过程进度展示功能. 第一种方法: 分析代码:违背依赖倒置原则 第6行: ProgressB

Observer pattern 观察者模式

一.认识观察者模式 我们看看报纸和杂志的订阅是怎么回事: 1.报社的业务就是出版报纸. 2.向某家报社订阅报纸,只要他们有新的报纸出版,就会给你送来,只要你是他们的订户,你就会一直收到报纸. 3.当你不想在看到报纸的时候,取消订阅,他们就不会送新的报纸来. 4.只要报社还在运营,就会一直有人或单位向他们订阅报纸或取消订阅报纸. 出版者+订阅者=观察者模式 如果你了解报纸的订阅是怎么回事,其实就知道观察者模式是怎么回事,只是名字不太一样:出版者改称为“主题”(subject),订阅者改称为“观察者

【设计模式】观察者模式 Observer Pattern

定义:观察者模式定义了对象之间的一对多依赖.当“主题”(Object)状态改变事,所有依赖它的“观察者”(Observer)都会受到通知并自动更新.主题支持观察者订阅和退订. 观察者模式提供了一种对象设计,让主题和观察者之间松耦合.改变主题或观察者一方不会影响另一方.因为两者是松耦合的. 参考: 设计模式学习笔记--Observer Pattern观察者模式

Design Pattern: Observer Pattern

1. Brief 一直对Observer Pattern和Pub/Sub Pattern有所混淆,下面打算通过这两篇Blog来梳理这两种模式.若有纰漏请大家指正. 2. Use Case 首先我们来面对一个老到跌渣的故事,并以从未听说过Observer Pattern为前提. 假设要设计一个新闻订阅系统,新闻分为商业.体育和八卦3种,而查收终端有PC.移动终端等,后续还不断增加新闻种类和查收终端. 需求如上,下面我们根据OOD的方式来构建概念模型. 新闻 <- 分类新闻 终端 <- 分类终端

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

先看下观察者模式的定义: The Observer Pattern defines a one-to-many denpendency between objects so that when one object changes state, all of its dependents are notified and updated automatically.:观察者模式定义了对象间一对多依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新. 观察者模式又叫发布-

C#设计模式(17)——观察者模式(Observer Pattern)

原文:C#设计模式(17)--观察者模式(Observer Pattern) 一.引言 在现实生活中,处处可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用.在这一章将分享我对观察者模式的理解,废话不多说了,直接进入今天的主题. 二. 观察者模式的介绍 2.1 观察者模式的定义 从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户.从中,我们就可以得出观察者模式的定义. 观察者模式定义了一种一对多的依赖