盘点android中常见的设计模式(八) -- 观察者模式

观察者模式:

什么是观察者模式(Observer Pattern)?这里我们举个栗子:一队警察部署在不同的位置观察着犯罪分子的活动,当犯罪分子进行某个特定的行为时,比如进行非法交易的时候,这队在不同位置的警察同时出击抓捕罪犯。这就是一种观察者模式的诠释。

观察者模式定义了一种一对多的依赖关系,当被观察者的状态发生改变时,所有依赖于它的观察者对象都会得到通知并作出自己的改变。这是一种行为型模式。

观察者主要有三大要素:被观察对象、观察者、他们之间的依赖方法。

观察者模式的优点:

  • 观察者和被观察者是抽象耦合的
  • 建立了一套触发机制。

 

Android中的使用:

我个人觉得观察者模式可能android中应用最为广泛的一种设计模式了。别的不说,就按钮的点击事件onClick而言,就可以看做为一种观察者模式,这个过程中Button其实可以被看做是被观察者,onClick事件可以看做是观察者,而setOnClickListener方法就是它们之间的添加依赖关系的方法。当Button状态发生改变时,即被点击后,则通知了onClick完成更新。

另外大家所熟知的Rxjava其核心思想也是一种观察者模式,最为直观地就是其五大基类之一的Observable,Observable通过subscribe方法去订阅Observer来完成。通过命名我们也能知道,Observable是被观察者,Observer是观察者,而subscribe方法则是它们之间的依赖方法。(需要注意的是Rxjava中的观察者模式观察者与被观察者的依赖关系是反着的,一般情况下应该是观察者去subscribe被观察者,这里则是被观察者去订阅观察者)。

接下来我们以一个简单的例子来说明观察者模式的简单代码实现,这个例子就是开头所提到的警察抓捕小偷的过程。第一步:我们需要创建一个Observer的抽象类,用来抽象观察者方法。

//被观察者的抽象方法
public abstract class Observer {
    //当被观察者状态改变时,所有观察者更新方法
    public abstract void update(boolean b);
}

第二步:创建被观察者对象,即是例子里的犯罪分子,并且定义一个集合observers用来存放所有的观察者对象,定义一个布尔型的isCrime来保存被观察者的状态,即犯罪分子是否实施犯罪。

/**
 * 被观察者对象 -- 犯罪分子
 */
public class Offender {
    //定义集合 存放所有观察者对象
    private List<Observer> observers = new ArrayList<>();

    private boolean isCrime;

    public boolean isCrime() {
        return isCrime;
    }

    public void setCrime(boolean crime) {
        isCrime = crime;
        notifyAllObservers();
    }

    //订阅方法 -- 添加与观察者的依赖关系
    public void subscribe(Observer observer){
        observers.add(observer);
    }
    
    //通知所有观察者更新
    public void notifyAllObservers(){
        for (Observer observer:observers) {
            observer.update(isCrime());
        }
    }
}

第三步:创建多个继承自Observer的观察者类并实现其update方法。

//观察者 -- A警察
public class PuliceA extends Observer {

    @Override
    public void update(boolean b) {
        if (b){
            Log.i("ledding", "PuliceA 开始抓捕");
        }else{
            Log.i("ledding", "PuliceA 继续观察");
        }
    }
}


//观察者 -- B警察
public class PuliceB extends Observer {

    @Override
    public void update(boolean b) {
        if (b){
            Log.i("ledding", "PuliceB 开始抓捕");
        }else{
            Log.i("ledding", "PuliceB 继续观察");
        }
    }
}

第四步:代码中实现使用。

        //创建被观察者-犯罪分子
        Offender offender = new Offender();
        //添加依赖关系
        offender.subscribe(new PuliceA());
        offender.subscribe(new PuliceB());

        //还没有实施犯罪
        offender.setCrime(false);
        //实施犯罪
        offender.setCrime(true);

最后来看下打印的日志是否实现了我们的预期。

打印日志图片

发布了17 篇原创文章 · 获赞 6 · 访问量 4345

猜你喜欢

转载自blog.csdn.net/ledding/article/details/105263767