`

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

阅读更多

Observer模式也叫观察者模式,是由GoF提出的23种软件设计模式的一种。Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。

本文介绍设计模式中的(Observer)模式的概念,用法,以及实际应用中怎么样使用Observer模式进行开发。

Observer模式的概念
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。

Observer模式的典型应用
- 侦听事件驱动程序设计中的外部事件
- 侦听/监视某个对象的状态变化
- 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者

Observer模式的优点
- 对象之间可以进行同步通信
- 可以同时通知一到多个关联对象
- 对象之间的关系以松耦合的形式组合,互不依赖

Observer模式的结构


Observer模式的角色:
Subject(被观察者)
    被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
ConcreteSubject
    被观察者的具体实现。包含一些基本的属性状态及其他操作。
Observer(观察者)
    接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
ConcreteObserver
    观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。

JDK对Observer模式的支持
JDK提供了对observer设计模式的支持:
- 通过java.util.Observable类扮演Subject角色,一个类只需通过继承java.util.Observable类便可担当ConcreteSubject角色;
- 通过java.util.Observer接口扮演Observer角色,一个类只需实现java.util.Observer接口便可担当ConcreteObserver角色。
- java.util.Observable的实现类通过调用setChanged()方法以及notifyObservers(Object)方法便可简单地通知Observer。
当然,我们也可以不使用JDK提供的类与接口而自己实现Observer模式。

Observer模式的应用范例

下面,我们来实现一个Observer模式用来模拟新闻订阅操作:
当一个新闻被发表时,系统一方面需要通知管理者审阅;另一方面需要通知订阅者。

文件一览:
Client
    测试类。

NewsPublisher
    相当于ConcreteSubject角色。该类继承相当于Subject角色的Observable类。

SubscriberObserver
    相当于ConcreteObserver角色。该类实现了相当于Observer角色的IObserver接口。当            NewsPublisher对象发生变化时得到通知,并向订阅者发送订阅邮件。

ManagerObserver
    相当于ConcreteObserver角色。该类实现了相当于Observer角色的IObserver接口。当            NewsPublisher对象发生变化时得到通知,并向管理者发送消息邮件。

News

    封装了新闻数据的类,与Observer模式无直接关系。

Observable
   
Subject角色

Observer

    Observer角色

下面看具体代码实现:
Client

package zieckey.designpatterns.study.observer.nojdk;

public class Client
{

    /**
     * Test Observer Pattern
     * --
     *
     */

    public static void main( String[] args )
    {
        NewsPublisher publisher = new NewsPublisher();
        
        //添加观察者对象

        publisher.register( new SubscriberObserver() );
        publisher.register( new ManagerObserver() );

        //发布新闻,触发通知事件

        publisher.publishNews( "Hello news", "news body" );
    }
}



NewsPublisher

package zieckey.designpatterns.study.observer.nojdk;


/**
 * Subject ROLE
 * NewsPublisher: news publisher
 *
 */

public class NewsPublisher extends Observable
{
    public void publishNews( String newsTitle, String newsBody )
    {
        News news = new News( newsTitle, newsBody );

        System.out.println( "News published:" + newsTitle );
        this.notifyAllObervers( news ); //通知各Observer,并发送一个名为news对象的消息


        //other process ... such as save news to database

    }
}


   

SubscriberObserver
  

package zieckey.designpatterns.study.observer.nojdk;

/**
 * Observer ROLE
 *
 */

public class SubscriberObserver implements IObserver
{

    public void update( Observable observee, Object param )
    {
        if ( param instanceof News )
        {
            mail2Subscriber( (News)param );
        }
    }

    private void mail2Subscriber( News news )
    {
        System.out.println( "Mail to subscriber. A news published with title : "
                + news.getTitle() );
    }
}




ManagerObserver

package zieckey.designpatterns.study.observer.nojdk;


/**
 * Observer ROLE
 *
 */

public class ManagerObserver implements IObserver
{

    public void update( Observable observee, Object param )
    {
        if ( param instanceof News )
        {
            mail2Manager( (News)param );
        }
    }

    private void mail2Manager( News news )
    {
        System.out.println( "Mail to Manager. A news published with title : "
                + news.getTitle() );
    }
}




News

package zieckey.designpatterns.study.observer.nojdk;

//data entity

public class News
{
    private String    title;
    private String    body;

    public News( String title, String body )
    {
        this.title = title;
        this.body = body;
    }

    public String getBody()
    {
        return body;
    }

    public void setBody( String body )
    {
        this.body = body;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle( String title )
    {
        this.title = title;
    }
}


   

Observable


package zieckey.designpatterns.study.observer.nojdk;

import java.util.ArrayList;

/**
 * Subject(被观察者)
 * 被观察的对象。
 * 当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。
 * Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
 *
 * @author zieckey
 *
 */

public class Observable
{
    private ArrayList < IObserver >    arrayList    = null;

    Observable( )
    {
        arrayList = new ArrayList < IObserver >();
    }

    public void register( IObserver observer )
    {
        arrayList.add( observer );
    }

    public void unregister( IObserver observer )
    {
        arrayList.remove( observer );
    }

    public void notifyAllObervers( Object arg )
    {
        for ( int i = 0; i < arrayList.size(); i++ )
        {
            arrayList.get( i ).update( this, arg );
        }
    }

}



IObserver

package zieckey.designpatterns.study.observer.nojdk;

/**
 *
 * Observer(观察者)
 * 接口或抽象类。
 * 当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
 *
 * @author zieckey
 *
 */

public interface IObserver
{
    public void update( Observable observee, Object param );
}



运行程序输出:

News published:Hello news
Mail to subscriber. A news published with title:Hello news
Mail to Manager. A news published with title : Hello news



应用场景和优缺点

       上面已经对观察者模式做了比较详细的介绍,还是那句话,人无完人,模式也不是万能的,我们要用好设计模式来解决我们的实际问题,就必须熟知模式的应用场景和优缺点:

       观察者模式的应用场景:

1、  对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。

2、  对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

观察者模式的优点:

1、  SubjectObserver之间是松偶合的,分别可以各自独立改变。

2、  Subject在发送广播通知的时候,无须指定具体的ObserverObserver可以自己决定是否要订阅Subject的通知。

3、  遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

观察者模式的缺陷:

1、  松偶合导致代码关系不明显,有时可能难以理解。(废话)

2、  如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)


相关原则

       相信大家现在对观察者模式都应该很清楚了吧!OK!那么,就像我们在前面的文章里反复强调的一样,设计原则远比模式重要,学习设计模式的同时一定要注意体会设计原则的应用。这里我们再来看看观察者模式里都符合那些设计原则。

1、  Identify the aspects of your application that vary and separate them from what stays the same. (找到系统中变化的部分,将变化的部分同其它稳定的部分隔开。)

在观察者模式的应用场景里变化的部分是Subject的状态和Observer的数量。使用Observer模式可以很好地将这两部分隔离开,我们可以任意改变Observer的数量而不需要去修改Subject,而Subject的状态也可以任意改变,同样不会对其Observer有任何影响。

2、  Program to an interface,not an implementation.(面向接口编程,而不要面向实现编程。)

SubjectObserver都使用接口来实现。Subject只需要跟踪那些实现了IObserver接口的对象,所以其只依赖于IObserver;而所有Observer都通过ISubject接口来注册、撤销、接收通知,所以它们也只依赖于 ISubject;所以这是面向接口编程的,这样的实现方式使得SubjectObserver之间完全没有任何耦合。

3、  Favor composition over inheritance.(优先使用对象组合,而非类继承)

观察者模式使用对象组合将Subject和若干observer联系起来。它们之间的关系不是通过类的继承而是在运行时的动态组合。

分享到:
评论

相关推荐

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

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

    设计模式-观察者模式-作业-observer.zip

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

    设计模式系列博客--观察者模式

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

    设计模式--观察者模式java例子

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

    设计模式C++学习之观察者模式(Observer)

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

    Observer 观察者模式 示例 源码 ----设计模式

    观察者模式 概述 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 适用性 1.当一个抽象模型有两个方面,其中一个方面依赖于另一方面。 将这二者封装...

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

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

    设计模式---观察者模式

    观察者模式是一种行为设计模式,它允许你定义一个订阅机制,可以及时地在对象之间传播状态变化。在Java中,观察者模式常用于构建事件驱动系统,使得多个对象能够监听并响应某个对象的状态改变。 首先,我们要理解...

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

    观察者模式,也被称为发布-订阅模式或事件驱动模式,是软件设计模式中的一种行为模式。这个模式的主要目的是在对象之间建立一种松散耦合的关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并...

    C++设计模式--观察者模式 demo

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它在C++中的应用广泛且实用。这种模式的核心思想是“主体”(Subject)与“观察者”(Observer)之间的松耦合关系,允许一个对象(即主体)的状态...

    Java 设计模式-观察者模式(Observer)

    结合微信公众号讲解观察者模式,生动形象,关键是上手快啊

    设计模式之观察者模式Java实现

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

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

    观察者模式(Observer)是软件设计模式中的一种行为模式,其主要目的是在对象之间建立一种松散耦合的关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式广泛应用于事件驱动...

    设计模式-观察者

    观察者模式(Observer Pattern)是行为设计模式的一种,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 观察者模式的核心思想是发布-订阅模型,其中...

    HeadFirst 设计模式学习笔记2--观察者模式 demo

    观察者模式是设计模式中的一种行为模式,它在软件工程中扮演着重要的角色,尤其是在构建可扩展和可维护的系统时。HeadFirst的设计模式系列书籍以其直观易懂的方式深受程序员喜爱,本笔记将深入探讨观察者模式的概念...

    设计模式--观察者 c++版本

    在给定的“设计模式--观察者 c++版本”中,我们主要关注的是观察者模式(Observer Pattern)在C++语言中的实现。观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,...

    设计模式-观察者模式.ppt

    观察者模式是一种行为设计模式,它允许你定义一个订阅机制,可以在对象事件发生时通知多个“观察”该对象的其他对象。这个模式的核心在于建立一种一对多的关系,当一个对象的状态改变时,所有依赖于它的对象都会得到...

    C#面向对象设计模式纵横谈(19):(行为型模式) Observer 观察者模式 (Level 300)

    **C#面向对象设计模式纵横谈(19)**:**观察者模式**(Observer Pattern)是行为型模式的一种,它在软件工程中扮演着至关重要的角色。观察者模式是一种设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态...

    [行为模式]head first 设计模式之观察者模式(observer)

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

    设计模式-观察者模式(讲解及其实现代码)

    总结来说,观察者模式是一种重要的设计模式,它允许对象在状态改变时自动通知其他对象,从而降低了系统各部分之间的耦合度,提高了代码的灵活性和可扩展性。在实际项目中,正确使用观察者模式可以有效地管理组件间的...

Global site tag (gtag.js) - Google Analytics