命令式 声明式 响应式 函数式

命令式编程(Imperative programming)

详细的命令机器怎么(How)去处理一件事情以达到你想要的结果(What)

例子:我晚上打车回家,司机不认识路,我需要一步一步告诉司机每个路口怎么走

1
2
3
4
5
6
7
var user
for(var i=0; i < user.length; i++) {
if(user.user_name == "Ben") {
print("find");
break;
}
}

声明式编程( Declarative programming)

只告诉你想要的结果(What),机器自己摸索过程(How)

例子:我晚上打车回家,只需要告诉司机我家在哪里即可

1
2
SELECT * from user
WHERE user_name = LiXiang

响应式编程(Reactive programming)

是使用异步数据流进行编程。本质上是对数据流或某种变化所作出的反应,但是这个变化什么时候发生是未知的,所以是基于异步、回调的方式在处理问题。
例子:我晚上打车回家,在滴滴上面下了订单发出信号,我可以在等待的时候随便做什么,不会干等着。(异步调用不阻塞)
司机接单,给我一个信号,那我就可以等司机到上车。(信号回调)
整个过程是异步回调的方式来进行的。这样我和司机都不用一直干等着,效率比较高。
代码例子可以参考RxJava/RxJS https://zhuanlan.zhihu.com/p/27678951 这篇文章里面有很详细的介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Disposable subscribe = Observable.just(url)
.subscribeOn(Schedulers.io())
.map(s -> {
ArrayList<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
params.add(new BasicNameValuePair("email", getEmail()));
params.add(new BasicNameValuePair("host_ip", getHostIp()));
params.add(new BasicNameValuePair("host_port", "10086"));
params.add(new BasicNameValuePair("package", getCurrentActivity().getPackageName()));
String executeGet = NetworkUtils.executePost(200 * 1024, s, params);
JSONObject object = new JSONObject(executeGet);
return object;
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object -> {
ToastUtils.showLongToast(getCurrentActivity(), "配置成功");
});

函数式编程(Functional programming)

函数式的代码是对映射的描述,在函数式语言中,函数作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合。

好处:首先,最直观的角度来说,函数式风格的代码可以写得很精简,其次,函数式的代码是“对映射的描述”,它不仅可以描述二叉树这样的数据结构之间的对应关系,任何能在计算机中体现的东西之间的对应关系都可以描述——比如函数和函数之间的映射;比如外部操作到 GUI 之间的映射(就是现在前端热炒的所谓 FRP)。它的抽象程度可以很高,这就意味着函数式的代码可以更方便的复用。

最后,可以很好的写出并行代码
代码例子(翻转二叉树):

1
2
3
4
5
6
data Tree a = Nil | Node a (Tree a) (Tree a)
deriving (Show, Eq)

invert :: Tree a -> Tree a
invert Nil = Nil
invert (Node v l r) = Node v (invert r) (invert l)

函数式编程和声明式编程有所关联,因为他们思想是一致的:即只关注做什么而不是怎么做。但函数式编程不仅仅局限于声明式编程。