观察者模式是经常使用的设计模式。正如“观察之意”,这个模式的作用就是观察某个对象是否改变,如果改变,则与它相关的对象也都发送相应的改变,从而达到联动效果。
这个模式涉及到的对象主要也是两个:
观察者对象、被观察的对象。
示例:
两个接口:一个观察者接口、一个被观察者接口(也就是观察目标)
/**
* 观察者对象
* @author xiaoqi
*
*/
public interface IObserver {
public void update(String info);
}
/**
* 被观察者
* @author xiaoqi
*
*/
public interface ITarget {
public void registerObserver(IObserver observer);
public void removeObserver(IObserver observer);
public void notifyDataChanged();
}
被观察者通常要实现上面三个方法用于动态的添加观察者与动态更新数据
具体实现:
public class ConcreteObserver implements IObserver {
public void update(String info) {
System.out.println(info);
}
}
/**
* 被观察者的具体实现
* @author xiaoqi
*
*/
public class ConcreteTarget implements ITarget {
private String newInfo;
private List<IObserver> listObserver = new ArrayList<IObserver>();
//添加观察者
public void registerObserver(IObserver observer) {
listObserver.add(observer);
}
//移除观察者
public void removeObserver(IObserver observer) {
if(listObserver.size()>0){
listObserver.remove(observer);
}
}
//更新数据
public void notifyDataChanged() {
for(IObserver ob : listObserver){
ob.update(newInfo);
}
}
public String getNewInfo() {
return newInfo;
}
//数据改变的同时动态改变其他被观察者状态
public void setNewInfo(String newInfo) {
this.newInfo = newInfo;
<span style="color:#FF0000;">notifyDataChanged();</span>
}
public List<IObserver> getListObserver() {
return listObserver;
}
public void setListObserver(List<IObserver> listObserver) {
this.listObserver = listObserver;
}
}
使用测试:
public class ObserverTest {
public static void main(String[] args) {
ConcreteObserver co1 = new ConcreteObserver();
co1.update("观察者1");
ConcreteObserver co2 = new ConcreteObserver();
co2.update("观察者2");
ConcreteTarget target = new ConcreteTarget();
target.registerObserver(co1);
target.registerObserver(co2);
target.setNewInfo("信息改变-------");
}
}
结果:
观察者1
观察者2
信息改变-------
信息改变-------
从使用的方法可以看出,本来co1和co2两个对象的内容是不同的,但是在调用register方法注册在观察者模式中,当被观察的目标状态发生改变的时候,co1、co2两个对象的内容也动态改变了,这就是观察者模式的作用。
Android中的ListView就用了观察者模式,当我们数据集合改变的时候,列表就会改变这就是观察者模式的原因。
看一下BaseAdapter源码:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public boolean hasStableIds() {
return false;
}
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();
}
/**
* Notifies the attached observers that the underlying data is no longer valid
* or available. Once invoked this adapter is no longer valid and should
* not report further data set changes.
*/
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
。。。。。。。
}
DataSetObservable就是观察者对象。
ListView在setAdapter的时候调用了registerDataSetObservable方法添加了观察者。当数据集合改变,我们会手动调用notifyDataSetChanged()方法来更新列表数据。
而这个方法正式调用了DataSetObservable的notifyChanged方法:
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* Invokes {@link DataSetObserver#onChanged} on each observer.
* Called when the contents of the data set have changed. The recipient
* will obtain the new contents the next time it queries the data set.
*/
public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
。。。
}
而notifyChanged方法则是遍历了所以的list,然后依次调用观察者的onChanged方法。从而让数据动态更新。DataSetObservable被观察对象的数据改变,使得所有观察者对象改变,这个联动的改变就是观察者模式的作用。