首页 > 编程知识 正文

什么是响应式框架,响应式编程 优点

时间:2023-05-04 08:56:07 阅读:166336 作者:1499

原文地址

本系列文章的索引: 《响应式Spring的道法术器》。

1响应编程之道1.1什么是响应编程? 在开始讨论响应编程(Reactive Programming )之前,让我们先看一下我们经常使用的一种强大的生产力工具——称为“响应范式”——电子表格。

举个简单的例子,某电商网站推出促销活动,每一个单品都可以参加“满199-40”活动,参加“满500包邮”。 食物nrdgb有选择障碍。 (当然,主要原因还是语言。 我很穷。 )他有先在Excel上根据预算计算自己要买的东西的习惯。

我想大家都用过Excel的公式。 这是一张购物车商品和订单的支付金额汇总表,其中包含几个公式:

上图蓝线为公式引用关系,“商品金额”为“单价x数量”得到,“满199-40”判断该商品金额是否满199,根据情况扣除40。 右侧的“订单总额”为“满199-40”列之和,“邮费”根据订单总额计算,成为“最终应付款”

1.1.1变化传递(propagation of change )为什么电子表格是“响应型模型”,因为“单价”和“数量”的任何变动,都会参照其单元(“监听”)实时更新计算结果

这是响应式的核心特点之一:变化传递(propagation of change)当某个单元格发生变化时,就像多米诺骨牌一样,直接引用它的其他单元格和间接引用的其他单元格都发生变化。

看这里,“切~不是支付金额吗? 你可能会说“购物网站有这个最基本的功能呢~”,这是“应答式”吗? 但是,与用户对话的系统都必须“响应”用户的对话~

但是在响应编程中,基于“变化传递”的特征,触发响应的主体发生了变化。 假设购物车管理和订单支付是两个不同的模块,或者至少是两个不同的类别——Cart和Invoice。 我们的代码可能是这样的:

Product.java (假设商品有两个属性name和price,为了简单起见,price不使用BigDecimal类型)。

public class product { privatestring name; private double price; //在生成方法、getters、setters } Cart模块中:

import com.example.Invoice; //2公共类别卡(publicbooleanaddproduct (product product,int quantity )……double figure=product.getprice ) ) invoice.update(figure; //1 . } .}是从Cart的对方那里更新Invoice对方的订单金额的方法; Cart代码需要import Invoice。

看看这个Excel,我们发现“订单总额”的计算公式不仅在自己的单元格中,还可以积极拦截和应对购物车数据的变化。 对于购物车,没有订单支付公式的参考。 是这样的:

假设数据流具有两个属性:要操作的产品和更改数量质量。

publicclasscartevent {私有产品产品; 私有输入质量; //在生成方法、getters、setters} Invoice模块中:

import com.example.cart//2public class invoice { . public invoice (cart ) . …this.Listenon ) cart; //回调方法publicvoidoncartchange (cart event )……}例如,Invoice的对象在初始化时声明监听cart对象,cart对象响应的事件

做过Java桌面开发的朋友可能会想到Java swing的各种侦听器,例如mouse监听器可以侦听鼠标操作并实时响应。 所以C/S的客户端总是比B/S的Web界面更有响应性呢。

所以,这里是一种生产者只负责生成并发出数据/事件,消费者来监听并负责定义如何处理数据/事件的变化传递方式

rong>。

那么,Cart对象如何在发生变化的时候“发出”数据或事件呢?

1.1.2 数据流(data stream)

这些数据/事件在响应式编程里会以数据流的形式发出。

我们再观察一下购物车,这里有若干商品,nrdgb每次往购物车里添加或移除一种商品,或调整商品的购买数量,这种事件都会像过电一样流过这由公式串起来的多米诺骨牌一次。这一次一次的操作事件连起来就是一串数据流(data stream),如果我们能够及时对数据流的每一个事件做出响应,会有效提高系统的响应水平。这是响应式的另一个核心特点:基于数据流(data stream)

如下图是nrdgb选购商品的过程,为了既不超预算,又能省邮费,有时加有时减:

这一次一次的操作就构成了一串数据流。Invoice模块中的代码可能是这样:

public Invoice(Cart cart) { ... this.listenOn(cart.eventStream()); // 1 ... } 其中,cart.eventStream()是要监听的购物车的操作事件数据流,listenOn方法能够对数据流中到来的元素依次进行处理。 1.1.3 声明式(declarative)

我们再到listenOn方法去看一下:

Invoice模块中,上边的一串公式被组装成如下的伪代码:

public void listenOn(DataStream<CartEvent> cartEventStream) { // 1 double sum = 0; double total = cartEventStream // 分别计算商品金额 .map(cartEvent -> cartEvent.getProduct().getPrice() * cartEvent.getQuantity()) // 2 // 计算满减后的商品金额 .map(v -> (v > 199) ? (v - 40) : v) // 将金额的变化累加到sum .map(v -> {sum += v; return sum;}) // 根据sum判断是否免邮,得到最终总付款金额 .map(sum -> (sum > 500) ? sum : (sum + 50)); ...

cartEventStream是数据流,DataStream是某种数据流类型,可以暂时想象成类似在Java 8版本增加的对数据流进行处理的Stream API(下节会说到为啥不用Java Stream)。

map方法用于对数据流中的元素进行映射,比如第一个将cartEvent中的商品价格和数量拿到,然后算出本次操作的金额;第二个判断是否能享受“满199减40”的活动。

这里的伪代码用到了lambda,它非常适用于数据流的处理。没有接触过lambda的话没有关系,我们后续会再聊到它。

这是一种“声明式(declarative)”的编程范式。通过四个串起来的map调用,我们先声明好了对于数据流“将会”进行什么样的处理,当有数据流过来时,就会按照声明好的处理流程逐个进行处理。

比如对于第一个map操作:

声明式编程范式的威力在于以不变应万变。无论到来的元素是什么,计算逻辑是不变的,从而形成了一种对计算逻辑的“绑定”。

再举个简单的例子方便理解:

a = 1;b = a + 1;a = 2;

这个时候,b是多少呢?在Java以及多数语言中,b的结果是2,第二次对a的赋值并不会影响b的值。

假设Java引入了一种新的赋值方式:=,表示一种对a的绑定关系,如

a = 1;b := a + 1;a = 2;

由于b保存的不是某次计算的值,而是针对a的一种绑定关系,所以b能够随时根据a的值的变化而变化,这时候b==3,我们就可以说:=是一种声明式赋值方式。而普通的=是一种命令式赋值方式。事实上,我们绝大多数的开发都是命令式的,如果需要用命令式编程表达类似上边的这种绑定关系,在每次a发生变化并需要拿到b的时候都得执行b = a + 1来更新b的值。

如此想来,“绑定美元政策”不也是一种声明式的范式吗~

总结来说,命令式是面向过程的,声明式是面向结构的

不过命令式和声明式本身并无高低之分,只是声明式比较适合基于流的处理方式。这是响应式的第三个核心特点:声明式(declarative)。结合“变化传递”的特点,声明式能够让基于数据流的开发更加友好。

1.1.4 总结

总结起来,响应式编程(reactive programming)是一种基于数据流(data stream)和变化传递(propagation of change)的声明式(declarative)的编程范式。

响应式编程的“变化传递”就相当于果汁流水线的管道;在入口放进橙子,出来的就是橙汁;放西瓜,出来的就是西瓜汁,橙子和西瓜、以及机器中的果肉果汁以及残渣等,都是流动的“数据流”;管道的图纸是用“声明式”的语言表示的。

这种编程范式如何让Web应用更加“reactive”呢?

我们设想这样一种场景,我们从底层数据库驱动,经过持久层、服务层、MVC层中的model,到用户的前端界面的元素,全部都采用声明式的编程范式,从而搭建一条能够传递变化的管道,这样我们只要更新一下数据库中的数据,用户的界面上就相应的发生变化,岂不美哉?尤其重要的是,一处发生变化,我们不需要各种命令式的调用来传递这种变化,而是由搭建好的“流水线”自动传递。

这种场景用在哪呢?比如一个日志监控系统,我们的前端页面将不再需要通过“命令式”的轮询的方式不断向服务器请求数据然后进行更新,而是在建立好通道之后,数据流从系统源源不断流向页面,从而展现实时的指标变化曲线;再比如一个社交平台,朋友的动态、点赞和留言不是手动刷出来的,而是当后台数据变化的时候自动体现到界面上的。

具体如何来实现呢,请看下一节关于响应式流的介绍。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。