观察者模式

简介: 观察者模式定义定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。应用场景有一个事件发生改变,需要通知其他多个对象时.

观察者模式

定义

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

应用场景

有一个事件发生改变,需要通知其他多个对象时.更多的应用于异步回调场景.

代码实现

UML类图结构

img_c9ce609931899b85971ac7de30a39dc2.jpe

代码实践

1.Subject主题

public class Subject {
    /**
     * 事件持有观察者的集合
     */
    private List<Observer> observers=new ArrayList<>();
    
    /**
     * 事件的状态
     */
    private String state;
    
    /**
     * 增加观察者
     */
    public void attach(Observer observer){
        
        observers.add(observer);
        
        
    }
    /**
     * 遍历通知观察者
     */
     public void notifyAllObservers(){
          for (Observer observer : observers) {
             observer.update(state);
          }
       }

     
     
    public String getState() {
        return state;
    }
    /**
     * 当状态发生改变,通知观察者
     */
    public void setState(String state) {
        this.state = state;
        notifyAllObservers();
    }     

}

2.观察者接口

public interface  Observer {
    /**
     * 更新观察者的状态
     */
    public void update(String state);

}

3.观察者具体实现

public class Observer1 implements Observer {

    @Override
    public void update(String state) {
        // TODO Auto-generated method stub
        System.out.println("Observer1 update:"+state);
    }

}

4.测试


public class Test {

    
    
    public static void main(String[] args) {
        
        //新建事件
        Subject subject=new Subject();
        //新建观察者
        Observer observer1=new Observer1();
        Observer observer2=new Observer2();
        //绑定观察者
        subject.attach(observer1);
        subject.attach(observer2);
        //更新事件状态
        subject.setState("我更新了");

    }
}

5.测试结果

Observer1 update:我更新了
Observer2 update:我更新了

ListView中的观察者模式

  • 在adapter中有一个内部类AdapterDataSetObserver,这个就是一个观察者.

  • 在listView.setadapter时候会初始观察者.

  • 在AdapterDataSetObserver的onChanged函数中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,更新用户界面。

源码分析

参考这是一篇关于listview源码的文章

BaseAdapter 中notifyDataSetChanged 调用的mDataSetObservable.notifyChanged();

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    // 数据集观察者,这里将观察者放到一个类中集中管理
    private final DataSetObservable mDataSetObservable = new DataSetObservable();

    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }

    /**
     * Notifies the attached observers that the underlying data has been changed
     * and any View reflecting the data set should refresh itself.
     * 当数据集用变化时通知所有观察者
     */
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }
}

在mDataSetObservable.notifyChanged()中遍历所有观察者,并且调用它们的onChanged方法。

public class DataSetObservable extends Observable<DataSetObserver> {
    /**
     * Invokes onChanged on each observer. Called when the data set being observed has
     * changed, and which when read contains the new state of the data.
     */
    public void notifyChanged() {
        synchronized(mObservers) {
            // 调用所有观察者的onChanged方式
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
    ...
}

继承自AbsListView的父类AdapterView的AdapterDataSetObserver,

  class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;
        // 上文有说道,调用Adapter的notifyDataSetChanged的时候会调用所有观察者的onChanged方法,核心实现就在这里
        @Override
        public void onChanged() {
            mDataChanged = true;
            mOldItemCount = mItemCount;
            // 获取Adapter中数据的数量
            mItemCount = getAdapter().getCount();

            // Detect the case where a cursor that was previously invalidated has
            // been repopulated with new data.
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {
                AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            // 重新布局ListView、GridView等AdapterView组件
            requestLayout();
        }

        ...

        public void clearSavedState() {
            mInstanceState = null;
        }

总结

所谓观察者模式,就是

多个观察者Observer -->观察attach--> 目标Subject的变化--->并通知刷新update

目录
相关文章
|
6月前
|
设计模式 消息中间件 Java
观察者模式
观察者模式
52 1
|
6月前
|
C++
【C++】—— 观察者模式
【C++】—— 观察者模式
|
6月前
|
设计模式 JavaScript 开发者
详细讲解什么是观察者模式
详细讲解什么是观察者模式
|
关系型数据库 API
观察者模式解读
观察者模式解读
|
6月前
行为型 观察者模式(发布订阅)
行为型 观察者模式(发布订阅)
39 0
|
6月前
|
设计模式 Java
【观察者模式】 ——每天一点小知识
【观察者模式】 ——每天一点小知识
5 # 观察者模式
5 # 观察者模式
36 0
|
设计模式 存储
设计模式-观察者模式(Observer)
设计模式-观察者模式(Observer)
96 0
|
XML 设计模式 Java
观察者模式(下)
观察者模式(下)
61 0
|
设计模式
观察者模式(上)
观察者模式(上)
82 0