内容简介:这一系列是我学习这个系列主要分为五个部分:这一篇我们讲要讲述一个实际的开发案例。在移动互联网时代,iOS家有APNs推送技术一统天下, Android有GCM,只不过在国内几乎都被国产厂商给阉割了。于是乎国内的Android推送服务 百花齐放,系统厂商提供的有华为,小米等,第三方提供的有极光,个推等。今天我们就讲讲如何 同时接入极光和小米的推送,从实际业务中看看如何进行抽象。
这一系列是我学习 Learn You a Haskell For Great Good
之后,总结,编写的学习笔记。
这个系列主要分为五个部分:
从移动端推送看什么是抽象以及如何抽象
这一篇我们讲要讲述一个实际的开发案例。在移动互联网时代,iOS家有APNs推送技术一统天下, Android有GCM,只不过在国内几乎都被国产厂商给阉割了。于是乎国内的Android推送服务 百花齐放,系统厂商提供的有华为,小米等,第三方提供的有极光,个推等。今天我们就讲讲如何 同时接入极光和小米的推送,从实际业务中看看如何进行抽象。
在建模过程中我们可以想象到,这是一个很好的应用面向对象思维的案例,首先推送服务 都需要提供这样几个功能:
push_id tag(标签,第三方提供的便利的群发推送方式) push_id push_id
于是我们可以写出这样一个基类:
import abc import requests class AbstractPush(metaclass=abc.ABCMeta): @abc.abstractmethod def push_by_push_id(self, push_id_list): pass @abc.abstractmethod def push_by_tag(self, tag_list): pass @abc.abstractmethod def update_tag(self, push_id, add_tag_list, remove_tag_list): pass @abc.abstractmethod def query_tag(self, push_id): pass
所有的子类都必须实现这些方法,例如我们有极光推送:
# jpusn.py from .base import AbstractPush class JPush(AbstractPush): def push_by_push_id(self, push_id_list): pass def push_by_tag(self, tag_list): pass def update_tag(self, push_id, add_tag_list, remove_tag_list): pass def query_tag(self, push_id): pass
和小米推送:
# mipusn.py from .base import AbstractPush class MiPush(AbstractPush): def push_by_push_id(self, push_id_list): pass def push_by_tag(self, tag_list): pass def update_tag(self, push_id, add_tag_list, remove_tag_list): pass def query_tag(self, push_id): pass
所以上面的代码实际上是这样的一种关系:
我们使用的时候就可以分别实例化不同的推送对象,然后调用对应的方法。 例如: MiPush().push_by_push_id("the_given_mi_push_id")
。
这就是经典的面向对象的思维。
如果我们反过来呢看看呢?我们已知所有的推送都实现了以上的方法,但是实际上我们 根本不需要知道它具体是什么推送,只需要知道它实现了这个方法就行。其实就是我们 常说的桥接模式,看一下 维基百科 的解释。
那么就会变成这样一种关系:
这是基于一种什么样的想法呢?我们假设每种推送都是一个黑盒子,没个黑盒子上都有四个洞 ABCD,不论是哪个黑盒子,从同一个编号的洞里丢东西进去,总是会从另一个固定的洞里出来。 就好象: A->C
, B->C
这样。这就是传说中的抽象。在Haskell中我们将会大量运用这种 能力。
其实我们在日常的编程中已经用到了这种能力,在 Java 中我们称之为接口( interface
)。 Golang中也是,Python中虽然没有明确的接口的概念,但是通过上面的示例代码我们便可以 够造出这种抽象,在C中我们往往通过函数指针和结构体指针来达到这种效果。
我们把上述的代码用 Go 来描述,就当作是我们的总结。
type Push interface { push_by_push_id(push_id_list []string) push_by_tag(tag_list []string) update_tag(push_id string, add_tag_list []string, remove_tag_list []string) query_tag(push_id string) }
抽象是软件开发中的一把利器,编程其实就是一个将复杂的任务拆解成无数个小任务,然后各个击破 的过程。而抽象则是将无数个小任务的共同点找出来,然后一箭n雕的一种能力。
这一篇其实是 https://jiajunhuang.com/articles/2017_08_12-tcp_ip.md.html 第一节 "为什么要分层" 的一个更详细的重复,但是抽象这么重要的能力,就算再多重申一百遍都 不为过。
总结
通过这一篇文章,我们从一个实际生产的案例看到了如何进行抽象,以及抽象和面向对象 过程的一些微小而又巨大的差异。接下来我们将从命令式语言跳到Haskell的具体语法, 看看在Haskell中,是否也有我们所谓的抽象和接口这些概念。
以上所述就是小编给大家介绍的《Haskell简明教程(二):从命令式语言进行抽象》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 命令式与声明式——Kubernetes部署教程
- 声明式 (declarative) vs 命令式 (imperative)
- Nim 1.0 发布,命令式编程语言
- Nim 0.17.2 发布,命令式编程语言
- 命令式组件Message、Dialog的主流写法分析
- Nim 0.18.0 发布,命令式编程语言
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Effective Java: Second Edition
Joshua Bloch / Addison-Wesley / 2008-05-28 / USD 54.99
Written for the working Java developer, Joshua Bloch's Effective Java Programming Language Guide provides a truly useful set of over 50 best practices and tips for writing better Java code. With plent......一起来看看 《Effective Java: Second Edition》 这本书的介绍吧!