您的位置:首页 > 其它

设计模式--[9]观察者模式

2017-01-05 14:46 155 查看

观察者模式

定义

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

应用场景

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

代码实现

UML类图结构



代码实践

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  观察者模式