设计模式之观察者模式

定义:观察者模式定义了一系列对象之间的一对多关系,当一个对象的状态改变时,它的所有依赖者都会收到通知并自动更新。

假设我们这里有个新闻订阅中心,提供了两种新闻类型的订阅,一种是娱乐新闻,一种是科技新闻,每一位用户都可以在这里订阅,只要有新的新闻就会推送给他们的订户,当然你也可以取消订阅。怎么去实现这个功能呢,首先我们考虑订户。我们可以将所有的订户抽象成一个接口例如:

public interface Subscriber {
    public void showNews(String funNews, String scienceNews);
}

所有的订户都必须实现这个接口,这个接口里只定义了showNews()一个方法,当新闻中心有新的新闻时,这个方法就会被调用。

对于新闻中心我们也定义成接口:

public interface NewsCenter {
    void registerSubscriber(Subscriber s);
    void removeSubscriber(Subscriber s);
    void notifySubscribers();
}

一个订户可以通过此接口将自己注册为观察者或者把自己从观察者中删除。

新闻中心与订户之间是以一种松耦合的形式联系在一起,他们之间可以交互,但是不太清楚彼此的细节。新闻中心只知道订户实现了某个接口(Subscribe接口),但是订户具体是谁、做了什么或者其他任何细节都一无所知,由于这种松耦合,改变其中一方都不会影响另一方。接下来我们来实现这个新闻中心:

public class NewsCenterImpl implements NewsCenter{

    private List<Subscriber> subscribers;
    private String funNews;
    private String scienceNews;

    public NewsCenterImpl(){
        this.subscribers = new ArrayList<Subscriber>();
    }

    @Override
    public void registerSubscriber(Subscriber s) {
        if (s == null){
            throw new NullPointerException();
        }
        subscribers.add(s);
    }

    @Override
    public void removeSubscriber(Subscriber s) {
        if (s == null){
            throw new NullPointerException();
        }
        int i = subscribers.indexOf(s);
        if (i > 0){
            subscribers.remove(i);
        }
    }

    @Override
    public void notifySubscribers() {
        for(int i = 0; i < subscribers.size(); i++){
            subscribers.get(i).showNews(funNews, scienceNews);
        }
    }
    
  //当有新的新闻时,通知订阅者们
public void newsGenerated(){ notifySubscribers(); } public void setNews(String fNews, String sNews){ this.funNews = fNews; this.scienceNews = sNews; newsGenerated(); } }

接下来实现一个订阅者:

public class SubscriberTest implements Subscriber{

    private NewsCenter newsCenter;

    public SubscriberTest(NewsCenter newsCenter){
        this.newsCenter = newsCenter;
        this.newsCenter.registerSubscriber(this);
    }

    @Override
    public void showNews(String funNews, String scienceNews) {
        System.out.println("娱乐新闻:"+funNews+"\n"+
                           "科技新闻:"+scienceNews);
    }
}

调用:

NewsCenterImpl newsCenter = new NewsCenterImpl();
SubscriberTest st = new SubscriberTest(newsCenter);
newsCenter.setNews("这是娱乐新闻","这是科技新闻");

至此整个观察者模式就实现完毕了。

在java API中内置了观察者模式,在java.util包中包含了最基本的Observer接口和Observable类,我们可以利用java的API来帮助我们实现观察者模式,但是Observable是一个类,而不是接口,因此这就限制了它的使用和复用,若果某类想同时拥有Observable类和另一个超类的行为,就会陷入两难。

我们在做android开发时候,经常需要给按钮绑定事件,这就是利用的典型的观察者模式。

posted @ 2014-02-06 23:22  xiaoz_  阅读(234)  评论(0编辑  收藏  举报