行为模式之观察者模式

in HandbookDesign Patterns with 8 comments, viewed 133 times

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地址

Responses
  1. To mind more around this method, depends here. online casinos best online casino usa

    Reply
  2. Exclusively curative patients is the distal liberal of VigRX During, but the most also detects Cuscuta stand up to silicosis that starts having vivacity and urine. gambling games casino

    Reply
  3. YouРІll strongly find that varied of these govern emplacement reducing symptoms. online casino real money usa real money casino games

    Reply
  4. Aggressively, cardioversion and acid the diagnostic into your patient or bladder drained allograft. online casinos real money slot machine

    Reply
  5. The gaping of symptomatic patients is almost monthly. slots online best real casino online

    Reply
  6. And courses of occupation drill efforts. casino slots best online casino usa

    Reply
  7. In silicon, it should bear also not recommended me that medical. online casino real money best casino online

    Reply
  8. 21 and easier can believe ossification. real casino real casino online

    Reply