設計模式,行爲模式之觀察者模式

1 概述

觀察者模式(observer Pattern),也叫發佈-訂閱模式,是一種很重要的行爲模式,它被廣泛運用在異步編程之中,可以說是異步編程的基礎。

2 觀察者模式

當我們需要關注某個對象的狀態時,可以不斷地輪詢,查看狀態是否變化,這也就是我們熟知的同步方式。然而這樣的方式效率很低,在對象狀態真正變化之前,任何的檢查都是對服務器資源的浪費。更好的方法是,當對象狀態改變的時候,可以有一種通知機制,告訴別人狀態發生了變化。觀察者模式,正是實現這種機制的關鍵。

觀察者模式中,觀察者可以註冊到自己感興趣的被觀察對象上,當被觀察對象的狀態發生變化,或某個事件放生時,逐個調用觀察者的方法來通知它們。這種異步的方式,很大程度上提高了運行效率

現實生活中,觀察者模式也很常見。比如網購了一件商品,我們不用時不時地去收貨點查看快遞有沒有到,而是當收到“商品已送達”的短信的時候,直接去取就行。此例中,當我們購買商品的時候,相當於關注了快遞的狀態,當狀態變爲“已送達”的時候,我們會得到通知。

3 案例

舉一個代碼案例。當我們關注了某個公衆號之後,便可以收到公衆號的文章推送,這其實就是典型的觀察者模式的例子:

public interface Observable<T> {
    void addSubscriber(Observer observer);
    void removeSubscriber(Observer observer);
    void publish(T object);
}

public class PublicAccount implements Observable<Article> {
    private String name;
    private Collection<Observer> subscribers;
    private Collection<Article> articles;
    PublicAccount(String name) {
        this.name = name;
        subscribers = new ArrayList<>();
        articles = new LinkedList<>();
    };
    @Override
    public synchronized void addSubscriber(Observer observer) {
        subscribers.add(observer);
    }
    @Override
    public synchronized void removeSubscriber(Observer observer) {
        subscribers.remove(observer);
    }
    @Override
    public synchronized void publish(Article article) {
        articles.add(article);
        System.out.println(name + " is publishing new article...");
        for (Observer subscriber : subscribers) {
            subscriber.update(article);
        }
    }
}

public interface Observer<T> {
    void update(T object);
}

public class ArticleFans implements Observer<Article> {
    private String name;
    ArticleFans(String name) {
        this.name = name;
    };
    @Override
    public void update(Article article) {
        System.out.println(name + " got article「" + article.getName() + "」");
    }
}

public class Article {
    private String name;
    private String content;
    Article(String name, String content) {
        this.name = name;
        this. content = content;
    };
    public String getName() {
        return name;
    }
}

public class Test {
    public static void main(String[] args) {
        PublicAccount publicAccount = new PublicAccount("Jump x Switch");
        ArticleFans link = new ArticleFans("Link");
        ArticleFans mario = new ArticleFans("Mario");
        publicAccount.addSubscriber(link);
        publicAccount.addSubscriber(mario);

        Article article = new Article("Pro Controller is on discount!", "……");
        publicAccount.publish(article);
    }
}

輸出:

Jump x Switch is publishing new article...
Link got article「Pro Controller is on discount!」
Mario got article「Pro Controller is on discount!」

我們關注了公衆號,其實就是把自己加入了公衆號的觀察者列表,當公衆號發佈新文章的時候,所有關注它的人,都會得到文章的推送。

JDK中的java.util.Observablejava.util.Observer,是觀察者模式的簡單實現,不過現實中使用不多(在SWT中應用很多)。
觀察者模式更多見於事件通知模型的框架中,如Netty中隨處可見ChannelFutureGenericFutureListener的組合;也可見於RedisPub/SubZooKeeperWatches……

4 總結

觀察者模式允許我們在對象狀態改變時得到通知,在一些高性能框架中得到了廣泛的應用,是異步編程的基礎。

文中例子的github地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章