观察者模式

本文是对文中参考文献的学习笔记

一、作用

观察者模式描述了一对多的关系。当一个对象的状态改变时,它的所有观察者都可收到通知并进行相应更新。

二、概念

UML

三、使用

1.抽象出被观察者java.util.Observable

实际使用时该抽象类/接口可省略

手动敲了下java.util.Observable,它是一个 class 而不是接口,鸿洋如是说:"基本上书上都对于Java的如此设计抱有反面的态度,觉得Java内置的观察者模式,违法了面向接口编程这个原则,但是如果转念想一想,的确你拿一个主题在这写观察者模式(我们自己的实现),接口的思想很好,但是如果现在继续添加很多个主题,每个主题的ddObserver,removeObserver,notifyObservers代码基本都是相同的吧,接口是无法实现代码复用的,而且也没有办法使用组合的模式实现这三个方法的复用,所以我觉得这里把这三个方法在类中实现是合理的"

/**
 * 重新调整了java.util.Observable的结构
 * @author yanglijin
 * @version v1.0
 * @since 2019-09-04
 */
public class Observable {
    // 标志被观察者是否有变化
    private boolean changed = false;

    private Vector < Object > obs;

    // 构建一个有0个观察者的被观察者
    public Observable() {
        obs = new Vector < > ();
    }

    // 1,管理观察者

    /**
     * 添加观察者
     * @param   o   an observer to be added.
     * @throws NullPointerException    如果添加的o为null时,会抛出异常
     */
    public synchronized void addObserver(Observer o) {
        if (o == null) {
            throw new NullPointerException();
        }
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /**
     * 删除观察者
     * @param o:传入null 对该方法无影响
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    // 2,对象状态变化时通知观察值
    public void notifyObservers() {
        notifyObservers(null);
    }

    /**
     *
     * @param arg:通知被观察者时携带的参数
     */
    public void notifyObservers(Object arg) {
        Object[] arrLocal;
        synchronized(this) {
            if (!hasChange()) {
                return;
            }
            arrLocal = obs.toArray();
            clearChanged();
        }
        for (int i = arrLocal.length - 1; i >= 0; i--) {
            ((Observer) arrLocal[i]).update(this, arg);
        }

    }

    public synchronized void setChanged() {
        changed = true;
    }

    public synchronized boolean hasChange() {
        return changed;
    }

    public synchronized void clearChanged() {
        changed = false;
    }

    public synchronized int countObservers() {
        return obs.size();
    }


}

2.实现具体的被观察者

public class MyBookManager extends Observable {
    private List mBooks;

    // 构造一个空的图书集合
    public MyBookManager(){
        mBooks = new ArrayList<>();
    }

    public void addBook(Book newBook) {
        mBooks.add(newBook);
        // 通知观察者
        setChanged();
        notifyObservers(newBook);
    }

}

3.抽象观察者

观察者具有的操作接口

public interface Observer {
    /**
     *
     * @param var1:被观察者对象
     * @param var2:传递给观察者的参数
     */
    void update(Observable var1, Object var2);
}

4.具体观察者

public class User implements Observer {
    private String userName;

    public User(String userName) {
        this.userName = userName;
    }

    @Override
    public void update(Observable observable, Object o) {
        if (o instanceof Book) {
            Book book = (Book) o;
            System.out.println(userName+"收到新书达到通知:"+book.toString());
        }
    }
}

5. 测试

@Test
public void testObserver() {
    MyBookManager bookManager = new MyBookManager();

    bookManager.addObserver(new User("小红"));
    bookManager.addObserver(new User("小明"));

    bookManager.addBook(new Book(1, "穆斯林的葬礼"));
}
小明收到新书达到通知:Book{id=1, name='穆斯林的葬礼'}
小红收到新书达到通知:Book{id=1, name='穆斯林的葬礼'}

参考文献

观察者模式 : 一支穿云箭,千军万马来相见
设计模式之观察者模式源码分析及实践
观察者设计模式在Android开发中的应用

你可能感兴趣的:(观察者模式)