函数编程演化历程
- 将业务代码直接写死代码里
- 将单一维度的条件作为参数传入方法中,方法内根据参数进行业务逻辑实现。
- 将多个维度的条件作为参数传入方法中,业务实现需要根据不同的参数处理不同的逻辑。
- 将业务逻辑封装为一个实体类,方法接受实体类为参数,方法内部调用实体类的处理逻辑。
- 调用方法时不再创建实体类,而是使用匿名函数的形式替代。
- 使用Lambda表达式替代匿名函数的形式,作为方法的参数,真正实现判断逻辑参数化传递。
案例
目的:针对不同需求对购物车的的商品进行过滤筛选
准备
- 商品对象
@Data @NoArgsConstructor @AllArgsConstructor public class Goods { // 编号 private Integer goodId; // 商品名称 private String goodName; // 商品类型 private Enum goodType; // 单价 private Double goodPrice; // 总价 private Double goodTotalPrice; // 数量 private Integer totalNum; }
- 商品枚举类
/**
* 商品类型的枚举类
*/
public enum GoodTypeEnum {
APPAREL(10,"服装类"),
DIGITAL(20,"数码类"),
BOOKS(30,"图书类"),
SPORTS(40,"运动类");
// 商品类型的编号
private Integer code;
// 商品类型的名称
private String name;
/**
* 构造函数
* @param code
* @param name
*/
GoodTypeEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
}
- 模拟商品数据
/** * 模拟商品数据 */ private static List<Goods> goodsList= new ArrayList<Goods>(){ { add(new Goods(111,"无人机", GoodTypeEnum.DIGITAL,10000.00, 10000.00,1)); add(new Goods(112,"VR一体机", GoodTypeEnum.DIGITAL,13000.00, 13000.00,1)); add(new Goods(113,"衬衫", GoodTypeEnum.APPAREL,100.00, 300.00,3)); add(new Goods(114,"牛仔裤", GoodTypeEnum.APPAREL,120.00, 120.00,1)); add(new Goods(115,"Java编程思想", GoodTypeEnum.BOOKS,80.00, 80.00,1)); add(new Goods(116,"Java核心技术", GoodTypeEnum.BOOKS,90.00, 90.00,1)); add(new Goods(117,"算法", GoodTypeEnum.BOOKS,60.00, 60.00,1)); add(new Goods(118,"跑步机", GoodTypeEnum.SPORTS,3600.00, 3600.00,1)); } }; /** * 获取商品列表 * @return */ public List<Goods> getGoodsList(){ return goodsList; }
实现
Version 1.0.0
/**
* Version 1.0.0
* 找出购物车中所有数码类产品
* @param goodsList
* @return
*/
public List<Goods> filterGoodsList(List<Goods> goodsList){
List<Goods> result = new ArrayList<>();
for (Goods goods : goodsList) {
if (GoodTypeEnum.DIGITAL.equals(goods.getGoodType())){
result.add(goods);
}
}
return result;
}
测试
@Test
public void version1(){
GoodsService goodsService = new GoodsService();
List<Goods> goodsList = goodsService.getGoodsList();
List<Goods> goods = goodsService.filterGoodsList(goodsList);
System.out.println(JSON.toJSONString(goods,true));
}
Version 2.0.0
/**
* 根据类型找出购物车中对应类型的产品
* @param goodsList
* @return
*/
public List<Goods> filterGoodsList(List<Goods> goodsList,GoodTypeEnum goodType){
List<Goods> result = new ArrayList<>();
for (Goods goods : goodsList) {
if (goodType.equals(goods.getGoodType())){
result.add(goods);
}
}
return result;
}
测试
@Test
public void version2(){
GoodsService goodsService = new GoodsService();
List<Goods> goodsList = goodsService.getGoodsList();
List<Goods> goods = goodsService.filterGoodsList(goodsList, GoodTypeEnum.SPORTS);
System.out.println(JSON.toJSONString(goods,true));
}
Version 3.0.0
/**
* 支持通过商品类型或者总价来过滤商品
* @param goodsList
* @param goodType
* @param totalPrice
* @param goodTypeOrPrice - true:根据商品类型 false:根据商品总价
* @return
*/
public List<Goods> filterGoodsList(List<Goods> goodsList,GoodTypeEnum goodType,Double totalPrice,boolean goodTypeOrPrice){
List<Goods> result = new ArrayList<>();
for (Goods goods : goodsList) {
//goodTypeOrPrice - true:根据商品类型 false:根据商品总价
if (goodTypeOrPrice && goodType.equals(goods.getGoodType())||
!goodTypeOrPrice && goods.getGoodTotalPrice()>totalPrice
){
result.add(goods);
}
}
return result;
}
测试
@Test
public void version3(){
GoodsService goodsService = new GoodsService();
List<Goods> goodsList = goodsService.getGoodsList();
List<Goods> goods = goodsService.filterGoodsList(goodsList, GoodTypeEnum.SPORTS,1000.00,false);
System.out.println(JSON.toJSONString(goods,true));
}
Version 4.0.0
/**
* 根据不同的goods判断标准,对商品列表进行过滤
* @param goodsList
* @param goodsPredicate(或者Predicate接口) - 不同的商品判断标准
* @return
*/
public List<Goods> filterGoodsList(List<Goods> goodsList,GoodsPredicate goodsPredicate){
List<Goods> result = new ArrayList<>();
for (Goods goods : goodsList) {
if (goodsPredicate.test(goods)){
result.add(goods);
}
}
return result;
}
/**
* Goods判断标准策略接口
*/
public interface GoodsPredicate {
/**
* 选择判断标准
* @param goods
* @return
*/
boolean test(Goods goods);
}
/**
* Goods商品类型为图书类型的判断标准
*/
public class BooksGoodsPredicate implements GoodsPredicate {
@Override
public boolean test(Goods goods) {
return GoodTypeEnum.BOOKS.equals(goods.getGoodType());
}
}
测试
@Test
public void version4(){
GoodsService goodsService = new GoodsService();
List<Goods> goodsList = goodsService.getGoodsList();
List<Goods> goods = goodsService.filterGoodsList(goodsList,new BooksGoodsPredicate());
System.out.println(JSON.toJSONString(goods,true));
}
Version 5.0.0
考虑到判断标准多样化,没必要为标准写一个类,可以使用匿名内部类根据情况直接判断
@Test
public void version5(){
GoodsService goodsService = new GoodsService();
List<Goods> goodsList = goodsService.getGoodsList();
List<Goods> goods = goodsService.filterGoodsList(goodsList,new GoodsPredicate(){
@Override
public boolean test(Goods goods){
return goods.getGoodTotalPrice()>5000;
}
});
System.out.println(JSON.toJSONString(goods,true));
}
Version 6.0.0
还可以进一步优化,使用lambda表达式
@Test
public void version6(){
GoodsService goodsService = new GoodsService();
List<Goods> goodsList = goodsService.getGoodsList();
List<Goods> goods = goodsService.filterGoodsList(goodsList,(Goods good) -> good.getGoodTotalPrice()>10000);
System.out.println(JSON.toJSONString(goods,true));
}