观察者模式

Posted this.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了观察者模式相关的知识,希望对你有一定的参考价值。

最近在学习使用RxJava的时候,了解到其功能的强大,可以简化很多的代码,让逻辑更清晰。其中,RxJava内部实现则用了观察者模式来实现。因此,在深入学习RxJava前就先把观察者模式理清楚先。
观察者模式中首先有两个角色,一个是被观察者(Subject),另一个是观察者(Observer)。顾名思义,观察者可以通过被观察者的动作来做出反应。举个例子,公司老板发布通知,是被观察者,而员工们是通知接受者,接受到老板的通知就做出相应动作,是观察者。可以用一个UML图说明下:

抽象Observer:

//观察者
public interface Observer 
    void update(String notice);
//被观察者
public class Subject 
    private List<Observer> list = new ArrayList<>();

    //订阅观察者
    public void subscribe(Observer observer) 
        list.add(observer);
    
    //取消订阅
    public void unsubscribe(Observer observer) 
        list.remove(observer);
    

    //提醒所有观察者
    public void notifyObservers(String notice) 
        for (Observer observer : list) 
            observer.update(notice);
        
    

具体实现类,公司老板(被观察者):

public class Boss extends Subject 
    private String notice;

    public String getNotice() 
        return notice;
    

    //发布通知
    public void publish(String notice) 
        this.notice = notice;
        notifyObservers(notice);
    
public class Stuff implements Observer 
    private int num;

    public Stuff(int num) 
        this.num = num;
    

    @Override
    public void update(String notice) 
        System.out.println("Stuff" + num + "收到通知:" + notice);
    

所有类实现后,创建一个Client类进行测试:

public class Client 
    public static void main(String[] args) 
        Boss boss = new Boss();
        for (int i = 0; i < 3; i++) 
            Observer stuff = new Stuff(i);
            boss.subscribe(stuff);
        
        boss.publish("放假");
    

结果:

Stuff0收到通知:放假
Stuff1收到通知:放假
Stuff2收到通知:放假

Android中观察者模式的应用

当ListView的内容发生改变时,我们可以通过adapter的notifyDataSetChange的方法来实现UI的更新。可以看看BaseAdapter的源码:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter 
    //设置一个观察者集合,DataSetObservable内部包含了一个观察者集合
    private final DataSetObservable mDataSetObservable = new DataSetObservable();

    //注册
    public void registerDataSetObserver(DataSetObserver observer) 
        //调用DataSetObservable的父类Observable的注册方法
        mDataSetObservable.registerObserver(observer);
    

    //取消注册
    public void unregisterDataSetObserver(DataSetObserver observer) 
        mDataSetObservable.unregisterObserver(observer);
    

    //提醒更新
    public void notifyDataSetChanged() 
        mDataSetObservable.notifyChanged();
    

    //省略部分代码

再看看观察者DataSetObservable的集合是怎么实现的:

public class DataSetObservable extends Observable<DataSetObserver> 

    //在Subject中调用了notifyChanged方法
    public void notifyChanged() 
        synchronized(mObservers) 
            for (int i = mObservers.size() - 1; i >= 0; i--) 
                // 每一个观察者都进行改变更新操作
                mObservers.get(i).onChanged();
            
        
    

    public void notifyInvalidated() 
        synchronized (mObservers) 
            for (int i = mObservers.size() - 1; i >= 0; i--) 
                mObservers.get(i).onInvalidated();
            
        
    

上述mObservers来自父类Observable:

//Observable被观察者,相当于Subject
public abstract class Observable<T> 
    //观察者集合,由子类知T泛型是DataSetObserver
    protected final ArrayList<T> mObservers = new ArrayList<T>();

    //添加观察者
    public void registerObserver(T observer) 
        //不为空且不存在已有就添加
        if (observer == null) 
            throw new IllegalArgumentException("The observer is null.");
        
        synchronized(mObservers) 
            if (mObservers.contains(observer)) 
                throw new IllegalStateException("Observer " + observer + " is already registered.");
            
            mObservers.add(observer);
        
    

    //取消注册观察者
    public void unregisterObserver(T observer) 
        if (observer == null) 
            throw new IllegalArgumentException("The observer is null.");
        
        //找到对应的观察者并删除
        synchronized(mObservers) 
            int index = mObservers.indexOf(observer);
            if (index == -1) 
                throw new IllegalStateException("Observer " + observer + " was not registered.");
            
            mObservers.remove(index);
        
    

    //取消所有注册
    public void unregisterAll() 
        synchronized(mObservers) 
            mObservers.clear();
        
    

以上是关于观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

浅谈java中内置的观察者模式与动态代理的实现

django的信号

设计模式之观察者模式

Zookeeper集群

zookeeper

ZooKeeper