`
frank-liu
  • 浏览: 1682522 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

再回首Observer Pattern

 
阅读更多

早些时候曾经写过一篇关于observer pattern的文章,当时是基于.net平台的event特性理解做了一点解读。时过境迁,一下又过去三年多了。再回过头来看这些东西的时候,感觉当初的说法还是过于教条和书面化,内容的深度还是不够。

一个想法

如果不是从一种严格的教科书定义来看observer pattern的话,我们可以从一些示例中引申出这种思想来。我们可以从一个报纸订阅发布的这个示例来考虑这个问题。假设我们有一个报纸的发行出版商,每经过一个阶段就会发行新的报纸或者杂志。这个时候我们就需要通知一些感兴趣的用户或者已经预订的用户。通知的形式可以是发邮件给用户,或者是寄送到用户的指定地址或者短信通知等等。

总的来说,就是我出版商这一方产生了一个有新报纸出版这个事件的时候,我们就需要通知相关的人。

有一种很笼统的思想如下,就是既然我有新报纸发行了,那就一个一个通知呗,这种思路的典型代码如下:

 

 

// 假定我们要提供一些比如期刊号或者推荐专栏之类的信息
public void notifyUsers()
{
    String journalNumer = getJournalNumber();
    String promotedColumn = getPromotedColumn();
    userA.sendEmail(journalNumer, promotedColumn);
    userB.deliverNewspaper(journalNumer, promotedColumn);
    userC.sendSMS(journalNumer, promotedColumn);
}

这种思路对应的类关系图比较直接简单,如下图:

 

我们如果仔细考虑上面的代码,就会发现其中存在如下的一些问题:

1. 我们是在通知的代码里直接对一个一个的用户对象来发送消息通知。这就有变动的可能。比如说以后如果有新加入的用户需要我们通知或者有的用户不需要了,我们就要在这部分代码里频繁的改动。

2. 由于要通知多个用户,如果每个用户被通知的方式都不一样,就没办法用一种统一的方式来处理,也不好提取出公共的地方。

总的来说,前面提到的代码我们就面临着两个变化,一个是接收消息变化通知的用户会变;另外就是每个用户接收通知的具体形式也不一样,也会变动。

报纸订阅的初步思路

结合前面提出的两个问题,我们来作进一步的思考。前面第一个问题是订阅用户的频繁变化。实际上,我们在这部分代码里更希望的就是针对所有已经登记注册的用户发送通知,具体哪些用户登记和取消不是我发送通知的方法应该关注的。而且,既然有用户可以加入和退出,我们就应该有一个可以允许用户登记和取消的功能。这样,我们就应该有registerObserver()和removeObserver()两个方法。为了保留所有登记的用户,我们可以简单的用一个ArrayList来保存。

这样,我们这两个方法就可能有如下方法的一种实现:

 

// observers 表示所有已经注册用户的列表,ArrayList

public void registerObserver(Observer o)
{
    observers.add(o);
}


public void removeObserver(Observer o)
{
      int i = observers.indexOf(o);
      if(i >= 0)
        observers.remove(i);
}

 看上去这部分代码是可行的,但是慢着。我们还忽略了一个简单的细节。既然我们要在registerObser和removeObserver方法里面来添加和移除用户,根据传进来的Observer参数,这些用户要么就必须是Observer类型或者是Observer类型的子类。这就正好也引入到我们前面碰到的第二个问题。

    第二个问题就在于我们通知的所有用户的方式不一样,那么我们是否可以针对向用户的通知提取出一个什么公共或者抽象的东西呢?假定我们向所有用户推送的基本是相同的信息,比如说报刊期号、报刊推荐专栏,那么我们可以提供一个统一的接口方法update()。每个不同的用户针对update作不同的实现,比如发邮件的就发邮件,发短信的发短信。

按照前面的讨论,我们的类图可以设计成如下:

 

在前面的设计中,我们就已经用到了封装变化以及面向抽象而不是具体类这两个面向对象的设计原则。

进一步的改进

再来看上面的设计,我们会发现,这其中还有一些可以进一步改进的地方。我们看类Publisher,其中包含有方法registerObserver, removeObserver这两个专门管理登记用户的方法。除了这两个方法以外,还包含一些比如获取发布信息,报纸刊号等功能的方法。再结合我们前面的面向抽象的思路想想,有两个理由,我们可以考虑作一点修改。一个就是如果后面还需要有一个新的类似的出版物,比如说这个出版机构要发行一种新的杂志,它也要采用类似的方式来通知用户的话,同样也需要有一个维护注册用户的方法。既然这些部分的功能几乎都是重复的,我们是否可以考虑将这部分的功能单独提取出来作为一个公共的父类或者接口呢?这样每个具体的子类只要更多关注自身的业务相关逻辑。可以说,兼顾到了面向抽象,也更加职责明确了。还有一个理由就是,如果我们需要做测试的话,面向具体的类反而被限死了,针对接口或者抽象类的话会更灵活一些。我们可以将以上的设计进一步改进成如下图:

这类图就是observer pattern的一个典型结构。

 

在java class library中的应用

在java本身的类库里有好几个地方是对observer pattern的实现。一个就是java.util.Observer和java.util.Observable.在这里java定义了一个Observer的接口,通过统一实现里面的update方法来实现对事件的相应。而Observable是一个具体的类。这里定义了添加和移除observer的方法,并实现了通知Observer的方法。不过由于是一个具体的类,对于某个要定义通知事件的类来说,显得稍微有点不够灵活。尤其是当某个要定义某个通知事件的类如果已经继承了某个类了,这就不能再通过继承Observable类来定义事件。

总结

        Observer pattern主要的目的是为了解决当一个对象变化的时候,需要通知和影响到其他相关联对象的耦合问题。怎么样保证达到一个松耦合的状态,使得关联对象的增减不会影响到我本身代码的变动。该模式主要分为两个大的部分,一个会发生事情的对象端,可以称其为Observerable,它主要是来事的,是事件的根源,有什么事情要变动了,它就会通知其他感兴趣的对象。它也提供了一个加入注册和退出的方法给另外一端的对象使用。另外一部分是对发生时间感兴趣的对象端,可以称之为Observer端。这一段的对象主要是接收消息通知,然后根据自身作相应的变化。

        这篇文章讲Observer pattern主要还是想作为一个引子,来引出后续的一些东西。实际上Observer pattern的思想在一些event based application以及reactor pattern的应用中都可以找到它的影子。理解了它,对于后续那些复杂的地方就方便多了。

参考材料

Head first design patterns.

  • 大小: 55.1 KB
  • 大小: 49.4 KB
分享到:
评论

相关推荐

    ObserverPattern

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,属于对象交互模式。它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于...

    详解Observer Pattern(观察者模式)在Java中的使用原理

    我们说学习Java应该从Swing开始,那么学习Swing最重要的思想就是对于观察者模式的理解(Observer Pattern)。因为,该设计模式在Java Swing框架中贯穿了始终。对于C#的委托、代理概念所使用的Callback(回调模式--...

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

    "ObserverPattern(订阅模式)3.zip"中的代码可能进一步阐述了观察者模式,这里的“订阅”一词可能意味着用户可以订阅特定的主题,只有当这些主题的状态改变时,用户才会收到通知。这与传统的观察者模式类似,但更加...

    ObserverPattern.unitypackage

    ObserverPattern.unitypackage是一个以unity为例写的观察者模式的应用举例。有需要的同学请下载!

    matlab开发-Observerpattern

    观察者模式(Observer Pattern)是设计模式中的一种行为模式,它允许一个对象,当其状态发生改变时,能够自动通知所有依赖它的对象。在MATLAB中实现观察者模式,可以帮助我们构建灵活、可扩展的代码结构,特别是在...

    Observer Pattern.rar

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件驱动的系统...

    ObserverPattern.zip

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在这个例子中,李先生是观察者,他希望得到气象站的天气预报更新和旅行社的...

    swift-Swiftµframework实现观察者模式Observerpattern

    Swift µframework 实现观察者模式Observer pattern

    Observer Pattern Example.rar

    观察者模式(Observer Pattern)是软件设计模式中的行为模式之一,其主要思想是定义一个一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式在软件开发中,尤其是...

    类似 Observer Pattern 的 NSNotificationCenter (实例)

    【标题】:“类似 Observer Pattern 的 NSNotificationCenter(实例)” 在iOS和macOS开发中,`NSNotificationCenter` 是一个关键的组件,它实现了一种类似于观察者模式(Observer Pattern)的机制。观察者模式是一...

    ObserverPattern2-Code5.zip

    这是关于C#中的观察者模式的教程文章。我们首先介绍作为GoF模式之一的经典观察者模式。观察者模式通过使用事件机制集成到C#中,这将在接下来讨论。然后,我们讨论与在C#中使用事件/事件处理程序相关的问题。

    02-observer-pattern

    观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式常用于事件驱动编程,例如用户...

    observer-pattern-demo 观察者模式示例

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在Java中,我们可以利用Java的内置接口`java.util.Observer`和`java.util....

    com.designpattern.state_observer.rar

    2. **观察者模式(Observer Pattern)**: 观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实时数据...

    Observer HeadFirst design pattern

    观察者模式(Observer Pattern)是软件设计模式中的行为模式之一,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式在C++中有着广泛的应用,...

    组合模式 Composite Pattern

    **组合模式**(Composite Pattern)是一种常用的结构型设计模式,主要用于构建具有层次结构的对象系统。它允许客户端以一致的方式处理单个对象和组合对象,简化了高层模块的调用。通过组合模式,可以将多个对象组织成...

    observer-pattern:New's Station Observer Pattern演示

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在Java中,这种模式通常通过实现`java.util.Observable`接口和`java.util....

    python-observer-pattern:Python中的观察者模式-代码示例

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象事件发生时通知多个“观察”该对象的其他对象。在Python中,我们可以利用内置的事件处理系统或者自定义类来实现这种模式。...

Global site tag (gtag.js) - Google Analytics