设计模式——观察者模式

观察者模式是一种非常常见的模式,它最常用在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,观察者模式就讲这些了,是不是很简单?感觉这是设计模式中最简单的一种了,不过这个模式真的很常用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值