Android观察者模式随记--(一)

前言

对于设计模式的学习,作者一开始是拒绝的。因为作者的Java基础和Android基础很烂。想着补一下Java坑,做做App练习,巩固基础,但是纠结了半天还是选择看看设计模式,毕竟还年轻,瞎搞呗。大致浏览了一下设计模式,发现确实很难懂。借着这个机会,我就想把自己的设计模式学习历程记录下来,希望能对迷茫的朋友有所帮助。当然了,新手上路,错误难免,请多指教!

观察者模式

  • 定义

装逼式:定义对象之间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
正常点说:几个对象去观察一个对象的状态,这一个对象状态发生改变时,会通知观察它的那几个对象,这几个对象观察到被观察对象状态发生变化了,然后自己就会做一些事情。当然,从这里就引出了两个关键类——Observer(观察者)Subject(被观察者)

Observer-Subject关系图
  • 应用

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。
比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

  • 实际操作

意图:定义对象间的 一对多 的关系。
用途:目标对象的状态改变,所有的依赖对象(观察者对象)得到通知。
实例:1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。 3、顾客在订奶站定牛奶,订奶站的人员只需保证牛奶送到订奶站,并通知顾客前来领取而不管顾客会把牛奶拿去喝还是洗脸;顾客接到订奶站的工作人员的通知,就去取牛奶,但并不关心他们是怎样把牛奶送到订奶站的。4、快递员送快递,打电话叫顾客领包裹。等等。
利弊: 利:1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。弊:1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化(理论的东西太死板,不好直观地反映问题,遇到具体的代码再说吧。)。
注意:
(1)在抽象类里有一个 ArrayList 存放观察者们。
(2)JAVA 中已经有了对观察者模式的支持类。JDK中提供的java.util.Observable实现类和java.util.Observer接口。
(3)避免循环引用。
(4)如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

  • 使用

Android中的观察者实现Observer接口,被观察者继承Obervable类

  • 观察者MyObserver实现Observer 接口。
  • 被观察者MyObservable继承Observable 类。
  • 观察者MyObserver向被观察者 MyObservable 订阅事件(将观察者MyObserver添加到被观察者MyObservable里面去)。
  • 被观察者MyObservable数据有改变,通知观察者MyObserver相应的数据有改变,请作出相应的操作。(核心操作)
  • 观察者MyObserver向被观察者 MyObservable取消订阅事件(将观察者MyObserver从被观察者MyObservable中移除)。
  • 入坑

看了部分资料,踩坑一步一步写了点:

观察者类(Object):

/**
 * @author bruno
 * @date: 2016/6/1
 *
 * TODO <>观察者类,实现Observer的接口。</>
 */
public abstract class MyObserver implements Observer {
    @Override
    public void update(Observable observable, Object data) {
    }
}

问:观察者必须是抽象类么?

被观察类(Subject):

/**
 * @author bruno
 * @date: 2016/6/1
 *
 * TODO <>被观察者类,继承Observable</>
 */

public class MyObservable extends Observable {

    //单例模式
    private volatile static MyObservable instance = null;

    private MyObservable() {
    }

    public static MyObservable getInstance() {
         if (instance == null) {
             synchronized (MyObservable.class) {
                 if (instance == null) {
                     instance = new MyObservable();
                 }
             }
         }
        return instance;
    }

    public void notifyDataChange(Data data) {
        //这是Observable的两个重要方法,数据改变和观察者的改变
        setChanged();
        notifyObservers(data);
    }
}

被观察者类直接继承Observable就行,这里使用了单例模式(双重校验锁)。关于单例模式,了解过一点,但是现在没怎么运用,所以还只是停留在概念上。这里有一篇不错的文章,如有问题,还望读者指出。

Data类:

/**
 * @author bruno
 * @date: 2016/6/1
 *
 * TODO <>Data数据类</>
 */
public class Data {

    private int dataChange;

    public Data() {
    }

    public int getDataChange() {
        return dataChange;
    }

    public void setDataChange(int dataChange) {
        this.dataChange = dataChange;
    }
}

这个没什么解释的,模拟数据。

Activity:

public class MainActivity extends AppCompatActivity {

    private MyObserver myObserver = new MyObserver() {
        @Override
        public void update(Observable observable, Object data) {
            super.update(observable, data);
            //观察者接受到被观察者的通知,来更新自己的数据操作。
            Data mData = (Data) data;
            Log.e("MainActivity",  "mData+++++++++++++" + mData.getDataChange());
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //模拟被观察者数据改变,更新数据。
        Data mData = new Data();
        mData.setDataChange(0);
        MyObservable.getInstance().notifyDataChange(mData);
    }

    @Override
    protected void onResume() {
        super.onResume();
        //观察者往被观察者中添加订阅事件。
        MyObservable.getInstance().addObserver(myObserver);
    }

    @Override
    protected void onPause() {
        super.onPause();
        //观察者从被观察者队列中移除
        MyObservable.getInstance().deleteObserver(myObserver);
    }

}

初探这坑不浅,还得慢慢踩。请多指教!

  • 参考资料

Android 中的观察者模式
Android 实现 listener: Observer pattern (观察者模式)
欢迎大家讨论交流指出问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容