Android中观察者模式

设计模式系列:
        0.Android开发常用设计模式;

        1. Android中单例模式;

        2. Android中建造者(builder)模式;

        3. Android中观察者模式;

        4. Android中原型模式;

        5. Android中策略模式;

        6.Android中工厂模式;

        7.Android中代理模式;

        8.Android中装饰者模式;

        9. Android中适配器模式;



  小白:毛毛哥,最近我搜索网上资料看观察者模式有点晕晕的

  这里写图片描述

  三毛:“这个说明你对接口的理解和使用不熟,另外百度出来的资料一大堆要么只说一半,要么还是只说一半,当然还有小部分好的,只是你搜索的姿势不对”

  小白:毛毛哥,给我讲讲观察者模式呗 这里写图片描述

一、常见需求场景

  三毛:”其实平常我们无处不接触观察者模式,像ListView、RecycerView…的item点击事件或普通控件(Button…)点击事件都使用了观察者模式,平常开发中界面A–>B–>C,然后要跟新A界面东西也可以使用观察者模式”

  小白:奥~,我一直以为只是接口和接口回掉,没想过还有这个名字

  三毛:”嗯,像平常的按钮点击事件监听,我给他加上名字,你就有点理解观察者模式的过程了,虽然Android系统给我们封装好了,但是不要紧,先看看,像下面”

//平常里的按钮事件监听例子
Button buttonA = (Button)findViewById(R.id.button1);
//注册观察者
buttonA.setOnClickListener(new OnClickListener()
{
  //观察者实现
    @Override
    public void onClick(View view)
    {
        //这里可以知道要观察的对象的一举一动...
    }
});

//拆分后
buttonA                 ---->要观察的对象//要观察谁谁谁
setOnClickListener()    ---->观察者
new OnClickListener()   ---->观察者的实现//在实现里可以知道要观察的对象的一举一动


  三毛:“OK,我的白,我想问下你,’在A界面设置夜晚/白天模式,项目里所有已经打开的界面都要接收到通知(没打开的不管)’你有什么思路可以实现呢”


二、基本解决方法

  小白:我想到有几种方法
    1)使用广播;
    2)使用第三方框架Eventbus;
    3)A设置好数据后保存到sharepreferences,,所有打开的界面都启动一个定时器,每2秒从sharepreferences获取一次数据。

三、基本解决方法存在的问题

  三毛:“可以哇,白白,能想到那么多方法,不过最后一个方法简直乱来这里写图片描述

  小白:啦啦啦~~~。

  三毛:“不过上面的几种方法也存在对应的问题”


  小白:这里写图片描述

  三毛:”1)广播不适用于发送大数据和频繁发送,因为当系统或应用发出广播时,将会扫描系统中的所有广播接收者,通过action匹配将广播发送给相应的接收者,接收者收到广播后将会产生一个广播接收者的实例,执行其中的onReceiver()这个方法,并且onReceive方法中不能执行太耗时的操作,也不要在里面创建子线程处理耗时操作(因为可能子线程没处理完,接收者就被回收了)”
      2)对于Eventbus看这个为什么你应该停止使用EventBus
      3)广播、EventBus、RxJava…很多热门的东西使用的都是观察者模式,只不过 他们使用场景要分清。

  小白:握草,毛毛哥继续

四、观察者模式写法

观察者模式定义:定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。


  三毛:”观察者模式按道理来说应该有2种,如下”

//第一种
JDK封装好了观察者设计模式的API支持:
1、java.util.Observable//要观察的对象(继承该类)
2、java.util.Observer接口//观察者(new个类实现该接口)
3、要观察的对象通过setChanged()方法以及notifyObservers(Object)方法就可以通知观察者

//第二种
不使用JDK提供的API,自己实现(虽然有点造轮子的感觉,可是自己写能更加随心所欲,是不辣~~)

  小白:奥,我终于知道为嘛毛毛哥说查到的资料都是只说一半一半的了

  三毛:“嗯,我先用JDK提供的API模拟上面的‘在A界面设置夜晚/白天模式,项目里所有已经打开的界面都要接收到通知(没打开的不管)’”

  小白:这里写图片描述

先写个要观察谁的类

//要观察皮肤设置(谁)
public class SkinObservable extends Observable {

   public void notificationUpdate(String content){
       //通知更新前准备准备
       setChanged();
       //准备好了,开始通知更新
       notifyObservers(content);
   }
}

然后写观察者类

public class SkinObserverB implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("更新辣,内容是:"+arg);
    }
}
//SkinObserverC,SkinObserverD,SkinObserverE...?
//多少个界面要更新皮肤就写多个个观察者,然后new出来?写一个放到基类就好了

设置皮肤就通知观察者更新

        //1 创建要观察谁(对象)
        SkinObservable skinObservable=new SkinObservable();
        //2 创建观察者
        SkinObserverB observerB=new SkinObserverB();
        //3 将观察者注册到要观察对象的观察者列表中
        skinObservable.addObserver(observerB);

        //如果这样写(不就和按钮点击事件一样辣?哈哈)
         //skinObservable.addObserver(new Observer() {
         //   @Override
          //  public void update(Observable o, Object arg) {

          //  }
       // });

        //4 发布消息(要观察的对象有消息就会通知观察者)
        skinObservable.notificationUpdate("更新皮肤辣~~");
        //5 退出了记得调用skinObservable.deleteObservers();或skinObservable.deleteObserver(Observer observer);移除观察者

  小白:好简单哇,毛毛哥,不过这个单词Observable和Observer我老是忘记搞混

  三毛:“这就是你的问题了,怪我咯”

  三毛:“下面不使用JDK提供的API,我们自己写”

写个接口,用来通知更新

public interface Observer2 {
    void updateSkin(Object object);
}

在写个要观察谁的类

public class SkinObserverB2 implements Observer2{
    @Override
    public void updateSkin(Object object) {
        System.out.println("更新辣,内容是:"+object);
    }
}

然后写个观察者的类(其实这个可以写成公共类,然后其他类继承它就好)

public class SkinObservable2 {
    private Object mObject;
    private List<Observer2> mObservers;

    public SkinObservable2(Object object) {
        mObject = object;
        mObservers = new ArrayList<>();
    }

    /**
     * 添加观察者
     *
     * @param observer2
     */
    public void addObserver(Observer2 observer2) {
        if (null != observer2)
            mObservers.add(observer2);
    }

    /**
     * 通知观察者更新
     */
    public void setUpdateListener() {
        for (Observer2 observer2 : mObservers)
            observer2.updateSkin(mObject);
    }

    /**
     * 释放内存,清空观察者
     */
    public void clearObservers() {
        if (null != mObservers)
            mObservers.clear();
    }
}

使用

        //1 创建要观察谁(对象)
        SkinObservable2 skinObservable2 = new SkinObservable2("更新皮肤辣~~");
        //2 创建观察者
        SkinObserverB2 skinObserverB2 = new SkinObserverB2();
        //3 将观察者注册到要观察对象的观察者列表中(和按钮点击事件一样辣)
        skinObservable2.addObserver(skinObserverB2);
        //4 发布消息(要观察的对象有消息就会通知观察者)
        skinObservable2.setUpdateListener();


五、观察者模式和普通写法区别


1、可以一对多,也可以多对一;
2、稳定的消息更新传递机制,并抽象了更新接口;
3、对象解耦(架构、模式啥的不都是为了解耦嘛,汗);
4、EventBus、广播、RxJava等都是使用观察者模式,它们使用场景要了解,而JDK已经提供了观察者模式的API,使用也不比它们难

猜你喜欢

转载自blog.csdn.net/u014769864/article/details/78252017