前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >重新认识观察者模式

重新认识观察者模式

作者头像
PhoenixZheng
发布2018-08-07 16:12:21
1950
发布2018-08-07 16:12:21
举报

对于观察者模式,我们知道它是设计模式的一种, 利用接口将数据和使用数据的对象进行解耦。 如果你是个老鸟的话,就知道 Java的 util的 Observer接口是实现观察者模式的关键。 如果你是初学者的话对于观察者模式也应该不陌生, 比如Android的BaseAdapter使用的就是观察者模式。

一个简单的观察者是怎么实现的?

首先当然是实现 Observer接口,

代码语言:javascript
复制
public interface Observer {
    void update(Observable o, Object arg);
}

`

举个例子,现在有个图书管理系统,学生可以跟图书馆借书, 这里假设有两个类, Student 和 Library, 从观察者角度来说的话,Student 是观察者,那么它需要实现接口

代码语言:javascript
复制
public class Student implements Observer {
    void update(Observable o, Object arg) {
        borrowBooks();
    }
}

`

接下来是 Library,它主要负责管理图书,当库存图书发生更改的时候,通知学生可以来借书了。

代码语言:javascript
复制
public class Library extends Observable {
    ArrayList<Book> books = ....;

    public void returnBook(Book book) {
        this.books.add(book);
        this.notifyObservers();
    }

    public void borrowBook(Book book) {
        this.books.remove(book);
        this.notifyObservers();
    }
}

`

这是个非常简单的例子,在客户端代码里只要往Library里添加观察者,就可以在每次数据发生更改时通过 update()方法通知到 Student实例。

代码语言:javascript
复制
....
    Library library = new Library();
    Student hanzo = new Student("hanzo");
    Student genji = new Student("genji");
    library.addObserver(hanzo);
    library.addObserver(genji);

`

并发情况下是怎么处理的

在并发情况下,观察者模式变的有点复杂起来。 比如上面的例子,图书馆每天都在不停的增加新的学生,也有学生在毕业离开, 也就是说当我们在通知学生的时候,手上的学生名单是在不停变化的,那么就得对它加锁。 另外一个,我们希望只有在数据发生变化的时候才通知学生, 意味着即使有人调用了 notify,但是数据没有变化的情况下,我们不会通知观察者。 对于这两个问题,源码是这么处理的,

代码语言:javascript
复制
public void notifyObservers(Object arg) {
    Object[] arrLocal;

    synchronized (this) {
        /* We don't want the Observer doing callbacks into
         * arbitrary code while holding its own Monitor.
         * The code where we extract each Observable from
         * the Vector and store the state of the Observer
         * needs synchronization, but notifying observers
         * does not (should not).  The worst result of any
         * potential race-condition here is that:
         * 1) a newly-added Observer will miss a
         *   notification in progress
         * 2) a recently unregistered Observer will be
         *   wrongly notified when it doesn't care
         */
        if (!hasChanged())
            return;
        arrLocal = obs.toArray();
        clearChanged();
    }

    for (int i = arrLocal.length-1; i>=0; i--)
        ((Observer)arrLocal[i]).update(this, arg);
}

`

它的逻辑是这样的 · 首先检查是否数据有发生变化 · 从已经注册的观察者列表中复制一份新数据 · 重置数据变化的 boolean 值 · 对这个过程加锁 · 逐个通知观察者

可以看出来观察者在极限情况下是有可能出现bug, 也就是注释中说的 · 刚刚加入的观察者收不到通知 · 刚刚移除的观察者还收到通知

对于观察者模式需要注意的也就是这么多了, 在开发中观察者可以很好的解耦UI和数据层,这对于代码结构来说很有帮助。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一个简单的观察者是怎么实现的?
  • 并发情况下是怎么处理的
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档