Java之函数式编程
Java从1.8以后引入了函数式编程,这是很大的一个改进。函数式编程的优点在提高编码的效率,增强代码的可读性。
先了解Java新引入的函数式编程,首先了解在没有函数式编程之前,函数编程的演变史。
实战案例:函数编程演变史
根据实际场景演示,为了应对不断变化的业务需求,代码的多个改进版本。
购物车案例
准备前置需求,购物车相关的实体类、枚举类、服务类等
下单商品实体类
1 | package com.function.shopping.cart; |
商品类型枚举
1 | package com.function.shopping.enums; |
购物车服务类
1 | package com.function.shopping.service; |
需求实现
version1.0.0
需求:找出购物车中所有电子产品
1 | /** |
测试代码
1 |
|
version2.0.0
需求:根据传入商品类型参数,找出购物车中同种商品类型的商品列表
1 | /** |
测试代码
1 |
|
version3.0.0
支持通过商品类型或总价过滤商品
1 | /** |
测试代码
1 |
|
小结
已经完成了三个需求的比较,发现根据条件过滤,只要条件(单条件或多条件)不同就会写相应的方法,因此会在代码中硬编码大量的判断条件,带来了代码不易阅读及难以维护,下面的版本展示优化硬编码带来的问题
version4.0.0
根据不同的Sku判断标准,对Sku列表进行过滤
传入一个判断标准,判断标准会动态的判断条件是否满足条件,从而是否达到条件进行返回,无形的将判断条件进行参数化,通过参数传入一个接口,接口的实现类定义了条件判断的具体实现,行为参数化传入到方法中,这其实是设计模式中的策略模式将数据的循环与处理分开了
1.定义Sku的选择谓词接口
1 | package com.function.shopping.service; |
2.实现接口条件判断的具体实现
条件一:对Sku的总价是否超出2000作为的判断标准
1 | package com.function.shopping.predicate; |
条件二:对Sku的商品类型为图书类的判断标准
1 | package com.function.shopping.predicate; |
3.具体使用
1 | /** |
测试代码
1 |
|
version5.0.0
使用策略模式将数据的循环与处理区分开,但是有带来一个问题,编写的判断条件有且只是用一次,若条件过多,我们会编写很多的判断条件类实现Predicate接口,而每次只是用一次,因此可以引用内部匿名类进行优化
测试代码
1 |
|
version6.0.0
在第五版的迭代后,使用了匿名类进行代码优化,好处是不用对接口进行实现,不用产生多余的类,只是用一次也没必要些那么多的类,但是在代码中的匿名类在写起来还是有些多,本次版本优化使用lambda进行优化
测试代码
1 |
|
这段代码与version6.0.0执行效果完全一样,但代码编写上出现了很大的不同,使用Lambda表达式替代匿名类,将行为参数化传递到代码中,由代码动态调用。
函数编程演化历程
- 将业务逻辑直接写死在代码里
- 将单一维度的条件作为参数传入方法中。方法内根据参数进行业务逻辑实现。
- 将多个纬度的条件作为参数传入方法中。业务实现需要根据不同的参数处理不同逻辑。
- 将业务逻辑封装为一个实体类,方法接收实体类为参数,方法内部调用实体类的处理逻辑。
- 调用方法时不在创建实体类,而是使用匿名函数的形式替代。
- 使用Lambda表达式替代匿名函数的形式,作为方法的参数。真正实现判断逻辑参数化传递。