写点什么

【函数式编程实战】(八) 如何将你的代码重构

  • 2022 年 7 月 26 日
  • 本文字数:2827 字

    阅读完需:约 9 分钟

前言📫 作者简介:小明 java 问道之路,专注于研究计算机底层,就职于金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的设计和架构📫 

🏆 Java 领域优质创作者、阿里云专家博主、华为云专家🏆

🔥 如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主哦

导读

我们学习了 java8 的特性,那么未来将如何写优雅的代码呢?怎么改善代码的可读性和灵活性呢?本文教你重构代码使用语言高级特性。

一、改善代码可读性、灵活性

增加代码可读性,什么是可读性,代码的可读性就是如何让人 一眼懂,别人理解更加简单,其二是让其他人怎么接手你的代码,因为你的代码很可能也经常会给别人维护

1、使用 Lambda 表达式

代码会更加简洁,减少冗长重复的代码,通过 Stream 流、方法引用、方法参数行为化等等方法,代码会更加直观,所以使用 Lambda 表达式将匿名类转换成更简洁的代码,可以使用 Intellj 自动重构

这里面要注意将匿名类转换为 Lambda 表达式,导致了隐晦调用,因为 Runnable、Task、都是目标类型,建议在构造时,使用显式的类型转换!

    /**     * 从匿名类到lambda     * 1、变量名问题     * 2、隐式调用问题     */    void runnnableTest() {        int a = 2;        Runnable r = new Runnable() {            @Override            public void run() {                int a = 2;                System.out.println(a);            }        };
Runnable r1 = (Runnable) () -> { int a1 = 2; // 如果定义 变量名为 a 编译错误 System.out.println(a1); }; }
复制代码

​2、用方法引用重构援用 Lambda 表达式

Lambda 表达式配合方法引用,将 lambda 行为参数化,这样代码是非常直观表达代码的意图的,建议重构时将 复杂逻辑,例如下面代码中的 filter 的实现封装成方法引用

public static void main(String[] args) {    List<OrderInfo> orderInfos = Arrays.asList(new OrderInfo("123", BigDecimal.ONE),            new OrderInfo("456", BigDecimal.TEN));
// 计算全部订单的交易金额 BigDecimal totalSubOrderAmt = orderInfos.stream() .filter(OrderInfo::filter) .map(OrderInfo::getOrderAmt) .reduce(BigDecimal.ZERO, BigDecimal::add);
// filter的实现封装成方法引用 BigDecimal totalSubOrderAmt1 = orderInfos.stream() .filter(orderInfo -> null != orderInfo && null != orderInfo.getOrderAmt() && orderInfo.getOrderAmt().compareTo(BigDecimal.ZERO) > 0) .map(OrderInfo::getOrderAmt) .reduce(BigDecimal.ZERO, BigDecimal::add);}

/** * 过滤合法订单 */public boolean filter() { if (null != this && null != this.getOrderAmt() && this.getOrderAmt().compareTo(BigDecimal.ZERO) > 0) return true; return false;}
复制代码

3、用 StreamAPI 重构数据处理​

​​建议所有的使用迭代器的处理,都转换为 Stream 流的形式,Stream API 可以更清晰的表达数据处理管道的意图,现在处理器的超线程、多核处理器可以对 Stream 优化

    public static void main(String[] args) {        // 迭代器 + if        Iterator<OrderInfo> it = orderInfos.iterator();        while (it.hasNext()) {            OrderInfo orderInfo = it.next();            if (orderInfo.getOrderAmt().compareTo(BigDecimal.ZERO) > 0) {                orderAmt.add(orderInfo.getOrderAmt());            }        }
// Stream流 + Lambda表达式 List<BigDecimal> collect = orderInfos.stream() .filter(orderInfo -> orderInfo.getOrderAmt().compareTo(BigDecimal.ZERO) > 0) .map(orderInfo -> orderInfo.getOrderAmt()).collect(Collectors.toList()); }
复制代码

4、代码灵活性

4.1、行为参数化

这个地方有 使用 Lambda 表达式进行行为参数化,将不同的行为作为参数传递给函数执行,不止这些还有 Predicate、Comparator 等对象提供的函数式接口

4.2、环绕执行

一些业务上的代码会有甚多同性,例如准备数据结构和清理回收对象等等等,完全可以减少重复代码,这块就是复用代码,本质上还是使用 Stream 和 Lambda 表达式以及函数式编程,但是会将代码扩展性和复用性应用到极致

二、函数式编程重构设计模式实战

1、策略模式

策略模式可以理解为一种通过算法解决一类问题的通用方案,策略模式包括该算法的接口,一个或多个接口的实现逻辑,以及策略对象,下面我们用 lambda 表达式实现


public static void main(String[] args) {    List<OrderInfo> orderInfos = Arrays.asList(new OrderInfo("123", BigDecimal.ONE),            new OrderInfo("456", BigDecimal.TEN));
// 这么写的意图,避免侧罗模式僵化的代码 // 实际上 Validator v1 = new Validator(new StrategyImpl()); 我们用的更多 Validator v1 = new Validator(o -> { System.out.println("订单号:" + o + " lambda下单成功"); return true; }); orderInfos.stream().forEach(orderInfo -> System.out.println(v1.submitOrder(orderInfo.getOrderId())));}

public interface Strategy { /** * 函数式接口 */ boolean submitOrder(String orderType);}
public class Validator { // 相当于一个中转站 private Strategy strategy;
public Validator(Strategy strategy) { this.strategy = strategy; }
boolean submitOrder(String orderType) { return strategy.submitOrder(orderType); }}

复制代码

2、模板方法模式

模板方法模式和上面的策略模式是行为模式,模板方法模式定义一个操作中的算法的接口,而将步骤延迟到子类实现类中。我们可以理解为字 lambda 表达式中,创建一个匿名内部类实现,然后重构成模板方法模式

3、观察者模式

观察者模式也是行为模式的一种,使用 lambda 表达式的时候,lambda 也要实现,但是 lambda 本质是想消除固定的代码,当我们业务大的时候,实际上不适合在 lambda 里面实现

4、责任链模式

责任链模式也是行为模式的一种,本质上写法和上面策略模式、模板方法、观察者相同,都是定义函数式接口,用 lambda 实现函数的逻辑。在上面策略模式有类似实现代码

5、工厂模式

在 Java8 以及高版本中,Collection 在 Java8 和 9 中的增强,我们之前介绍了集中静态工厂,以及创建出来的副本的一些特性,本章不再赘述

总结

我们学习了 java8 的特性,那么未来将如何写优雅的代码呢?怎么改善代码的可读性和灵活性呢?本文实际上是前面 7 篇的一个总结与实战应用,本讲包含使用 Lambda 表达式、方法引用、StreamAPI、行为参数化、重构设计模式的应用,相信读者对写法上的重构有了一定的思想。

发布于: 刚刚阅读数: 4
用户头像

物有本末,事有终始。知所先后,则近道矣 2020.03.20 加入

🏆CSDNJava领域优质创作者/阿里云专家博主/华为云享专家 📫就职某大型金融互联网公司后端高级工程师 👍专注于研究计算机底层/Java/架构/设计模式/算法

评论

发布
暂无评论
【函数式编程实战】(八) 如何将你的代码重构_设计模式_小明Java问道之路_InfoQ写作社区