你手机中的观察者模式

原创 2017年09月19日 09:27:24

自定义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分析-漂亮的解耦套路》供大家学习参考


参考资料

版权声明:本文原创作者:谷哥的小弟 http://blog.csdn.net/lfdfhl

相关文章推荐

Docker_入门?只要这篇就够了!(纯干货适合0基础小白)

与sgy一起开启你的Docker之路 关键词: Docker; mac; Docker中使用gdb无法进入断点,无法调试; 写在前面 这篇博客适合谁? 对于Docker并不了解,只是有一点模糊的...

想要清肠排毒,就喝汁己青汁!

保持肠胃畅通,对于我们的身体是非常重要的。积累毒素会影响我们气色和皮肤。只有身体排毒好了,才能让身体更加轻盈人也更加精神。 日常多加注意一些小细节可帮助你减少毒素积累。 多喝水 早晨最好空腹喝水...

史上最简单的 MySQL 教程(三)「 MySQL 数据库」

MySQL 数据库MySQL 数据库是一种C\S结构的软件,即分为:客户端和服务端。若想访问服务器,必须通过客户端;服务器应该一直运行,客户端则在需要使用的时候运行。

Node.js开发入门—使用对话框ngDialog

做网站经常会遇到弹出对话框获取用户输入或弹出对话框让用户确认某个操作之类的情景,基于AngularJS的扩展模块ngDialog可以帮我们优雅地完成这类事情。
  • foruok
  • foruok
  • 2015-09-06 07:15
  • 13230

ACM竞赛路上亲爱的坑们

写在前边:这些梗都是敝人自己做题和比赛时曾经坑过自己的地方,特别在这里记录一下,所有的链接都是本博客中的题解链接(有大致题意说明和代码),原题请到OJ上自行寻找。目的是提升自身姿势。欢迎大佬们给我提出...

经验分享-前端与后端的接口、HTML分离

在WEB项目中 前后端不分离多人开放效率还不及一个人开发效率来的高,今天分享一个概念

java实现二维码([带]logo)的绘制和解析(zxing by google)

二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础...

Java基础之(三十七)Java多线程编程<二>

控制线程join线程Thread提供了一个线程等待另一个线程完成的方法:join方法。当在某个程序执行流中调用其他线程的join方法,调用join方法的那个线程将被阻塞,直到被join方法加入的joi...

std::map 如何使用结构体作为自定义键值

在使用map时,有时候我们需要自定义键值,才能符合程序的需要。 比如我们需要使用自定义的结构体来作为map的键值.
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)