你手机中的观察者模式


自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理


探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制


Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南


版权声明


引子

做Android开发的童鞋都知晓目前在开发中最流行的套餐RxJava+Retrofit。嗯哼,前两天和同事吃饭,他无意间提起一个异步的问题;我说:可以用RxJava试试。这个哥们放下筷子,一本正经地告诉我:别用那玩意,不好用。

“不好用?”我疑惑地问到
“嗯”
“怎么不好用了?”
“反正就是感觉有点怪,一会儿观察,一会儿被观察,搞不清楚”

嗯嗯,听他说完这些,我大概明白了:他对RxJava的困惑其实是源于对观察者模式的陌生。没事儿,我们按照以往的套路来一起学习观察者模式。


观察者模式详细示例

在正式进入该设计模式之前,我想问一下:你们平常都用微信干什么呢?

“聊天”
“发朋友圈”
“逛微店”
“约…..”

好了,打住,我知道你想说什么了;再说下去我就要打马赛克了。你想想还有别的么?

“别的?除了这些,我还看微信公众号,关注自己喜欢的内容”

好嘞,就从微信公众号入手!平常我们关注一个微信公众号,当它推送新内容时,手机界面上就会出现一个红色的小点提醒我们查看详细内容。换句话说:我们订阅了公众号,当它有新消息时就会自动告知我们。再说得通俗点:相当于我们自己是观察者,在观察微信公众号,公众号就是被观察者。现在,我们用代码来模拟这个过程:

package cn.com;

/**
 * 原创作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */

public interface Subscription {
    public void addUserAccount(UserAccount userAccount);
    public void deleteUserAccount(UserAccount userAccount);
    public void sendMessage(String message);
}

建立抽象的被观察者

package cn.com;

import java.util.ArrayList;

/**
 * 原创作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */

public class SubscriptionAccount implements Subscription{
    private ArrayList<UserAccount> userAccountArrayList;

    public SubscriptionAccount(){
        userAccountArrayList=new ArrayList<>();
    }

    @Override
    public void addUserAccount(UserAccount userAccount) {
        if (userAccount!=null){
            userAccountArrayList.add(userAccount);
        }
    }

    @Override
    public void deleteUserAccount(UserAccount userAccount) {
        if (userAccount!=null){
            userAccountArrayList.remove(userAccount);
        }
    }

    @Override
    public void sendMessage(String message) {
        if(message!=null){
            for(UserAccount userAccount:userAccountArrayList){
                userAccount.receiveMessage(message);
            }
        }
    }
}

具体的被观察者,也就是刚才提到的微信公众号实现抽象被观察者。在此模拟微信公众号几个常用的方法:添加用户,删除用户,发送消息。

package cn.com;

/**
 * 原创作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */

public interface User {
    public void receiveMessage(String message);
}

抽象观察者。

package cn.com;

/**
 * 原创作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */

public class UserAccount implements User{

    private String name;

    public UserAccount(String name){
        this.name=name;
    }
    @Override
    public void receiveMessage(String message) {
        System.out.println(name+",收到消息:"+message);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

具体的观察者实现抽象观察者,也就是微信公众号的订阅者,比如我们自己。好了,现在微信公众号有了,用户也有了,我们来测试一把:

package cn.com;
/**
 * 原创作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
public class Test {

    public static void main(String[] args) {
          SubscriptionAccount subscriptionAccount=new SubscriptionAccount();
            UserAccount userAccount1=new UserAccount("老王");
            UserAccount userAccount2=new UserAccount("小弟");
            UserAccount userAccount3=new UserAccount("包包");
            subscriptionAccount.addUserAccount(userAccount1);
            subscriptionAccount.addUserAccount(userAccount2);
            subscriptionAccount.addUserAccount(userAccount3);
            subscriptionAccount.sendMessage("有心课堂新课程上线啦");

    }

}
  • 创建三个用户,老王,小弟,包包
  • 微信公众号添加这三个用户
  • 微信公众号发布消息

请看,控制台输出日志:

老王,收到消息:有心课堂新课程上线啦
小弟,收到消息:有心课堂新课程上线啦
包包,收到消息:有心课堂新课程上线啦

嗯哼,看到了么?三个微信用户都收到了微信公众号发布的消息。我们平常订阅微信公众号的本质是:微信公众号记录下我们的微信账号。所以,当它有新消息推送时瞅瞅自己的小本子上记录了谁就发送给谁。

看完这个小例子,我们再来梳理一下观察者模式。

  • 该模式中存在观察者和被观察者
  • 观察者和被观察者通过订阅发生关联关系
  • 当被观察者发出消息后,所有观察者均会收到消息

OK,当你看完了这个例子,再看RxJava的代码:

observable.subscribe(observer);

是不是就反应过来了呢?很多初学者看到这句代码的时候都会抓狂:怎么会是被观察者订阅了观察者?!!不该是观察者订阅被观察者么?!!其实,不必过于纠结文字表述的细节,重要的是明白其中的思想,它和我们刚才的:

  subscriptionAccount.addUserAccount(userAccount);

难道不一样么?就是同一回事!没啥不同的。我们在思考问题的时候,不能单纯地只站在生活的角度来看,也不能光从计算机的角度来考虑;而是要把两者结合起来,不要钻牛角尖,认死理。


小感悟

很多刚开始做开发的童鞋喜欢拿着一本厚厚的设计模式在角落里默默地啃。学习的劲头很足,态度也很端正,配得上10086个赞。在此,我也想提醒一下小伙伴们:学习态度和努力程度固然非常重要,但是我们也要注意学习方法。抛开实际应用和业务逻辑单纯地看设计模式是很难理解其精髓的。我们不妨将设计模式和自己的实际工作结合起来学习,比如做Android开发的小伙伴可结合Android源码或者非常流行的第三方库来深入地研究设计模式,在此推荐一篇《Retrofit分析-漂亮的解耦套路》供大家学习参考


参考资料

上一篇:一起玩转树莓派(2)——从双色LED灯开始


下一篇:使用对象模型来创建内容类型