设计模式总结之观察者模式(Subject/Observer Publisher/Subscriber)

  • A+
所属分类:设计模式

观察者模式在实际中用的非常多,这里的subject/observer(主题/观察者)也被称为publisher/subscriber

(发布者/订阅者)。我个人觉得发布订阅这种叫法更好理解。比如微信里订阅公众号,当公众号发布新消息时,你的微信会自动收到消息推送。这个听起来很神奇,居然可以自动收到消息。但其实弄懂这个模式后你会发现这个其实很简单。

为什么订阅者可以自动收到消息?其实说白了,就是发布者对象里有一个订阅者对象的list,当发布者发布新消息时,循环这个订阅者的list,并调用订阅者对象的update方法。也就是说,并不是发布者来更新订阅者的,而是发布者调用订阅者自己的update方法让订阅者自己更新的。怎么样?是不是很简单。

原理清楚后,这个模式也就基本清楚了。首先抽象出两个接口,分别是发布者和订阅者的接口。发布者接口为Subject,由于里面有一个订阅者list,所以有注册订阅者(registerObserver),删除订阅者(removeObserver),通知订阅者(notifyObserver)三个方法。订阅者接口为Observer,里面有update方法,当发布者调用notifyObserver方法时,会调用订阅者的update方法来更新自己。

这样设计以后,需要增加一个订阅者时,只需要注册进发布者的list里即可,不需要修改之前的代码,这样就遵守了开放(易于扩展)封闭(不修改原来的代码)原则。

下面来说一下使用java内置的观察者模式。

Java已经帮我们准备好了上面所说的两个接口,分别是Observable类(注意这是一个抽象类,对应上面的Subject接口)和Observer接口(对应上面的Observer接口)。Observerable之所以设计为抽象类,是因为它把registerObserver,removeObserver,notifyObserver这三个方法都已经封装好了,不用我们自己实现,更方便。Observer里与上面一样,只有一个update方法。

需要注意的是,在调用notifyObserver方法之前,必须先调用setChanged()方法,来告诉java状态已经改变。我想可能大多数人跟我一样觉得这样做很麻烦,没什么必要。我调用notifyObserver不就是默认已经是要改变了吗?看了《Head First设计模式》一书后,才发现这样做是很有必要的。setChanged()方法可以让你在更新观察者时,有更多的弹性。你可以更适当的通知观察者。有的时候,并不是每次更新都需要通知观察者。

传递数据有两种方法,一种是“推”(push)给观察者,另一种是观察者来“拉”(pull)数据。

看下update方法的两个参数

Update(Observerable o, Object arg)

当你想推数据时,将数据放到arg参数中,当你想拉数据时,从Observerable 对象(这是一个发布者的对象)里取即可。

还有一点需要注意的是,用java内置的观察者模式,每个观察者被通知的顺序是随机的,如果你的程序对顺序有要求的话,你就得自己实现观察者模式了。

下面是一个完整的例子。

package com.java.api.observer;

import java.util.Observable;

/**
 * 主题
 */
public class Person extends Observable {
    private  String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        this.setChanged();
        this.notifyObservers(name);
    }
}

 

package com.java.api.observer;

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


/**
 * 观察者1
 */
public class Observer1 implements Observer {
    public void update(Observable o, Object arg) {
        String name = (String) arg;
        System.out.println("Observer1 have recived changes!" + " name is " + name);
    }
}

 

package com.java.api.observer;

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

/**
 * 观察者2
 */
public class Observer2 implements Observer {
    public void update(Observable o, Object arg) {
        String name = (String) arg;
        System.out.println("Observer2 have recived changes!" + " name is " + name);
    }
}

 

package com.java.api.observer;

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

/**
 * 观察者3
 */
public class Observer3 implements Observer {
    public void update(Observable o, Object arg) {
        String name = (String) arg;
        System.out.println("Observer3 have recived changes!" + " name is " + name);
    }
}

 

package com.java.api.observer;

/**
 * 测试类
 */
public class ObserverTest {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.addObserver(new Observer1());
        p1.addObserver(new Observer2());
        p1.addObserver(new Observer3());
        p1.setName("dfs");
        p1.setName("dfs222");
    }
}

 

ZPY

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: