定义:
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
简单分析:
观察者模式.png
实例分析:
观察者模式应该包含以下角色:
1抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
2.具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
3.抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
4.具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
代码简单实现:
1.抽象主题:
/**
* 抽象被观察者
* @author Administrator
*
*/
public class AbstractSubject {
/**
* 保存注册观察者对象
*/
private List<Observer> list=new ArrayList<>();
/**
* 添加观察者
* @param observer
*/
public void attach(Observer observer)
{
list.add(observer);
}
/**
* 删除观察者
* @param observer
*/
public void detach(Observer observer)
{
list.remove(observer);
}
/**
* 更新所有注册的观察者
* @param content
*/
public void notifyObservers(String content)
{
for(Observer observer:list)
{
observer.update(content);
}
}
}
2.具体主题
public class ConcreteSubject extends AbstractSubject {
}
3.抽象观察者(Observer)角色
public interface Observer {
/**
* 更新接口
* @param state
*/
public void update(String state);
}
4.具体观察者
public class ConcreteObserver implements Observer{
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
public void update(String content) {
System.out.println(name+": "+content);
}
}
5.执行
public class Client {
public static void main(String[] args) {
ConcreteSubject subject=new ConcreteSubject();
Observer observer1=new ConcreteObserver("观察者一");
Observer observer2=new ConcreteObserver("观察者二");
Observer observer3=new ConcreteObserver("观察者三");
subject.attach(observer1);
subject.attach(observer2);
subject.attach(observer3);
subject.notifyObservers("被观察者 发生了变化");
}
}
Android源码:
在Android中也提供了一个类Observable用于观察者模式,下面看看Observable 的源码
package android.database;
import java.util.ArrayList;
/**
* Provides methods for (un)registering arbitrary observers in an ArrayList.
*/
public abstract class Observable<T> {
/**
* The list of observers. An observer can be in the list at most
* once and will never be null.
*/
protected final ArrayList<T> mObservers = new ArrayList<T>();
/**
* Adds an observer to the list. The observer cannot be null and it must not already
* be registered.
* @param observer the observer to register
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is already registered
*/
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);
}
}
/**
* Removes a previously registered observer. The observer must not be null and it
* must already have been registered.
* @param observer the observer to unregister
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is not yet registered
*/
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);
}
}
/**
* Remove all registered observer
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
在Android中最常用的应用:
在ListView中Adapter中favoritesAdapter.registerDataSetObserver(mDataSetObserver);;数据改变之后会自动调用:mDataSetObserver里面的方法;如:
DataSetObserver mDataSetObserver = new DataSetObserver() {
@Override
public void onChanged() {
if (favoritesAdapter.getCount() <= 0) {
showNoDeviceHint();
} else {
hiddenNoDeviceHint();
}
loadingImageButton.setVisibility(View.GONE);
super.onChanged();
}
@Override
public void onInvalidated() {
super.onInvalidated();
}
};
总结:观察者模式何时适用?
1.当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中可以使他们各自独立地改变和复用。
2.当对一个对象的改变需要同时改变其它对象,而不知道具体由多少对象有待改变。
3.当一个对象必须通知其他对象,而它又不能假定其他对象是谁,换言之,你不希望这些对象是紧密耦合的。让耦合的双方都依赖于抽象,而不是依赖于具体。
其他模式,会继续更新……