观察者模式是一种非常常见的模式,它最常用在GUI系统和订阅发布系统。像Android系统中的View的各种listener用到的就是观察者模式。使用观察者模式一个重要的原因就是解耦,将被观察者和观察者之间解耦,使得他们之间的依赖减小。
一,定义:
观察者模式是定义一种一对多的依赖关系,使得当一个对象状态改变时,所有依赖于它的对象都会受到通知,然后依赖于它的对象可以根据需求去做相应的操作。
二,UML类图
观察者模式UML类图如下:
- Subject:抽象主题,这是个抽象类,它是被观察的角色。抽象主题把所有观察者对象的引用保存在一个集合里面,抽象主题提供接口,可以增加和删除观察者对象。
- ConcreteSubject:抽象主题的实现类,具体主题,也叫具体被观察者。在具体主题内部状态发生改变时,给所有注册过的观察者发送通知。
- Observe:抽象观察者,观察者的抽象类,定义了更新接口,当被观察者状态发生改变时,会受到通知更新自己。
- ConcreteObserve:具体观察者,该角色实现抽象观察者所定义的更新接口,当收到被观察者通知时更新自己。
在实际的应用中,我们也不一定说非要严格按照上面的UML类图中描述的那样得有:抽象主题、抽象主题实现、抽象观察者、具体观察者。对于一般的情况我们可以省略抽象主题,只用具体主题。
三,实例
我们以一个Android的项目来举例说明观察者模式。情景是这样的:观察者观察用户点击返回键,当用户点击返回键时,观察者要收到通知。Talk is cheap,show me the code。
首先具体被观察者代码如下:
/**
* Created by zhuzhipeng on 16/4/16.
* 具体被观察者
*/
public class Observable {
private List<IBackPressedListener> mBackPressedList = new ArrayList<>();
private static final String TAG = "Observable";
/**
* 注册观察者
* @param backPressedListener
*/
public void addBackPressedListener(IBackPressedListener backPressedListener){
if(!mBackPressedList.contains(backPressedListener)){
mBackPressedList.add(backPressedListener);
}
}
/**
* 注销观察者
* @param backPressedListener
*/
public void removeBackPressedListener(IBackPressedListener backPressedListener){
if(mBackPressedList.contains(backPressedListener)){
mBackPressedList.remove(backPressedListener);
}
}
public void onBackPressed(){
Log.d(TAG,"onBackPressed in Observer");
for (int i = 0 ; i < mBackPressedList.size(); i++){
mBackPressedList.get(i).notifyBackPressed();
}
}}
List用户保存观察者对象引用,提供两个方法用于注册和注销观察者。onBackPressed()方法供我们的Activity调用,当然你也可以直接把Activity当成一个具体的被观察者,这里为了更好的阐述我们上面UML类图的关系,定义了一个具体被观察者,至于没有提供抽象主题,前面已经说明原因了。
然后就是观察者接口和接口的实现类。
观察者接口,没什么好说的,一个接口而已。
/**
* Created by zhuzhipeng on 16/4/16.
*/
public interface IBackPressedListener {
void notifyBackPressed();
}
实现类也很简单,这里定义了两个观察者接口实现类。
/**
* Created by zhuzhipeng on 16/4/16.
* 观察者1
*/
public class BackObserverOne implements IBackPressedListener {
public static final String TAG = "BackObserverOne";
@Override
public void notifyBackPressed() {
Log.d(TAG,"notifyBackPressed");
}
}
/**
* Created by zhuzhipeng on 16/4/16.
* 观察者2
*/
public class BackObserverTwo implements IBackPressedListener {
public static final String TAG = "BackObserverTwo";
@Override
public void notifyBackPressed() {
Log.d(TAG,"notifyBackPressed");
}
}
最后看下测试用的Activity类,也很简单,在onCreate()方法里面注册观察者,onDestroy()方法里面注销观察者。在onBackPressed()方法中,具体被观察者对象会通知观察者用户按了返回键。
public class MainActivity extends ActionBarActivity {
private static final String TAG = "MainActivity";
private Observable mObservable;
private BackObserverOne mObserverOne;
private BackObserverTwo mObserverTwo ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mObservable = new Observable();
mObserverOne = new BackObserverOne();
mObserverTwo = new BackObserverTwo();
mObservable.addBackPressedListener(mObserverOne);
mObservable.addBackPressedListener(mObserverTwo);
}
@Override
public void onBackPressed() {
super.onBackPressed();
mObservable.onBackPressed();
}
@Override
protected void onDestroy() {
super.onDestroy();
mObservable.removeBackPressedListener(mObserverOne);
mObservable.removeBackPressedListener(mObserverTwo);
}
}
最后看下我们所打印的log:
OK,观察者模式就讲这些了,是不是很简单?感觉这是设计模式中最简单的一种了,不过这个模式真的很常用。