讲师中心 微信公众号
AI工具推荐 视频效率加速

Java代码重构:通过方法提取优化类内重复逻辑

秋雪吖_5101

秋雪吖_5101

发布时间:2025-08-28 15:26:50

|

941人浏览过

|

来源于php中文网

原创

java代码重构:通过方法提取优化类内重复逻辑

本文探讨了如何在Java类中通过方法提取来消除重复代码,特别是在处理实体集合并进行数据转换的场景。核心策略是将重复的业务逻辑封装到相关实体类的新方法中,从而提高代码的封装性、可读性和可维护性,同时避免在多个方法中重复编写相同的数据处理逻辑。

在软件开发中,代码重复是一个常见的问题,它不仅增加了维护成本,还容易引入潜在的bug。当一个类中的多个方法执行相似的数据转换或集合处理逻辑时,这通常是进行重构的信号。本教程将通过一个具体的案例,演示如何利用方法提取(Method Extraction)这一重构技术,有效地解决类内代码重复问题。

识别重复代码模式

考虑以下两个Java方法,它们分别负责映射用户实体到DTO和更新用户资源:

原始方法一:map 方法

protected UserDTO map(UserEntity entity) {
    var result = new UserDTO();
    // 重复代码片段开始
    var userRoles = entity.getRoles().stream()
            .map(RoleEntity::getId)
            .map(String::valueOf)
            .collect(Collectors.toList());
    // 重复代码片段结束
    result.setId(entity.getId().toString());
    result.setLastAccessDate(entity.getLastAccessDate());
    result.setRoles(userRoles);
    if (entity.getEmail() != null) {
        var email = new UserDTO.Email(entity.getEmail(), EMAIL_TYPE);
        result.setEmails(List.of(email));
    }
    return result;
}

原始方法二:updateUser 方法

立即学习“Java免费学习笔记(深入)”;

public UserResource updateUser(String id, UserResource updatedUser) {
    var optionalUser = userRepository.findById(Integer.valueOf(updatedUser.getUserName()));
    // 重复代码片段开始
    updatedUser.setRoles(optionalUser.get().getRoles()
            .stream()
            .map(RoleEntity::getId)
            .map(String::valueOf)
            .collect(Collectors.toList()));
    // 重复代码片段结束
    updatedUser.setLastAccessDate(optionalUser.get().getLastAccessDate());
    var entity = mapToUserEntity(updatedUser);
    userRepository.save(entity);
    return updatedUser;
}

在这两个方法中,以下代码片段是完全重复的:

.getRoles().stream()
.map(RoleEntity::getId)
.map(String::valueOf)
.collect(Collectors.toList());

这段代码的作用是从 UserEntity 中获取角色列表(List),然后将其转换为一个包含角色ID字符串的列表(List)。

Java Api Extractor
Java Api Extractor

从 Java 项目中提取 Controller 层接口定义为 JSON 数据。

下载

解决方案:方法提取与封装

解决这种重复代码的最佳实践是将该逻辑封装到一个独立的方法中。关键在于选择合适的方法归属。考虑到这段逻辑是关于 UserEntity 内部角色数据的转换,将其直接添加到 UserEntity 类中是更符合面向对象设计原则的做法。这不仅提高了 UserEntity 的封装性,也使得 UserEntity 自身能够更好地管理和提供其内部数据的不同表示形式。

1. 在 UserEntity 类中添加新方法

我们将提取的逻辑封装为 getRoleIds() 方法,并将其添加到 UserEntity 类中。

// UserEntity.java
public class UserEntity {
    private Integer id;
    private String email;
    private Date lastAccessDate;
    private List<RoleEntity> roles; // 假设RoleEntity包含getId()方法

    // ... 其他属性、构造函数、getter/setter ...

    /**
     * 获取用户所有角色的ID列表。
     * 将List<RoleEntity>转换为List<String> (角色ID)。
     * @return 包含角色ID字符串的列表。
     */
    public List<String> getRoleIds() {
        if (this.roles == null) {
            return Collections.emptyList(); // 或根据业务需求返回null
        }
        return this.roles.stream()
                .map(RoleEntity::getId)
                .map(String::valueOf)
                .collect(Collectors.toList());
    }
}

// RoleEntity.java (示例)
public class RoleEntity {
    private Integer id;
    private String name;

    // ... 其他属性、构造函数、getter/setter ...

    public Integer getId() {
        return id;
    }
    // ...
}

2. 更新调用方方法

现在,原始方法中的重复代码可以被简洁地替换为对 entity.getRoleIds() 的调用。

优化后的 map 方法

protected UserDTO map(UserEntity entity) {
    var result = new UserDTO();
    var userRoles = entity.getRoleIds(); // 直接调用UserEntity中的新方法
    result.setId(entity.getId().toString());
    result.setLastAccessDate(entity.getLastAccessDate());
    result.setRoles(userRoles);
    if (entity.getEmail() != null) {
        var email = new UserDTO.Email(entity.getEmail(), EMAIL_TYPE);
        result.setEmails(List.of(email));
    }
    return result;
}

优化后的 updateUser 方法

public UserResource updateUser(String id, UserResource updatedUser) {
    var optionalUser = userRepository.findById(Integer.valueOf(updatedUser.getUserName()));
    // 确保optionalUser不为空,实际生产中应进行null检查或使用orElseThrow
    if (optionalUser.isPresent()) {
        updatedUser.setRoles(optionalUser.get().getRoleIds()); // 直接调用UserEntity中的新方法
        updatedUser.setLastAccessDate(optionalUser.get().getLastAccessDate());
    } else {
        // 处理用户不存在的情况,例如抛出异常
        throw new UserNotFoundException("User with username " + updatedUser.getUserName() + " not found.");
    }
    var entity = mapToUserEntity(updatedUser);
    userRepository.save(entity);
    return updatedUser;
}

注意事项与最佳实践

  1. 封装性提升: 将数据转换逻辑放在 UserEntity 内部,使得 UserEntity 对其自身的数据表示拥有更强的控制权,外部类无需关心其内部角色列表的具体转换细节,只需调用一个高层次的方法即可获取所需结果。
  2. 可读性与维护性: 新方法 getRoleIds() 具有清晰的名称,准确表达了其意图,使得调用方代码更加简洁易懂。如果未来角色ID的转换逻辑发生变化(例如,需要过滤特定类型的角色),只需修改 UserEntity 中的 getRoleIds() 方法,而无需改动所有调用它的地方。
  3. 选择合适的封装位置: 在本例中,将方法添加到 UserEntity 是最合适的,因为它处理的是 UserEntity 的内部数据。如果重复的逻辑不紧密依赖于某个特定实体,而是一个通用的工具函数,则可以考虑创建一个独立的工具类或私有辅助方法。
  4. 方法命名: 确保新方法的名称清晰、简洁,并准确反映其功能。例如,getRoleIds() 比 transformRolesToIds() 更为直接。
  5. 空值处理: 在 getRoleIds() 方法中,对 this.roles 进行空值检查是一个良好的实践,以避免 NullPointerException。

总结

通过方法提取和恰当的封装,我们成功地消除了类内的重复代码,提高了系统的可维护性和可读性。这个案例强调了在重构过程中,不仅要识别重复代码,更要思考将这些重复逻辑封装到何处才能最大化地提升代码质量和符合面向对象设计原则。将与特定实体数据紧密相关的逻辑放置在该实体类内部,是实现高内聚、低耦合的有效手段。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6839

2023.08.02

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

7015

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

362

2025.11.27

C++ 面向对象编程与设计模式实践
C++ 面向对象编程与设计模式实践

本专题整合了 C++ 面向对象编程的核心机制,涵盖类的定义与访问控制、构造函数与析构函数、拷贝语义与移动语义、继承与虚函数多态、抽象类与接口、运算符重载、友元函数等关键知识点,同时结合单例模式、工厂模式、观察者模式、策略模式等常用设计模式的 C++ 实现,帮助开发者写出结构清晰、易于维护的面向对象代码。

364

2026.04.09

Java 面向对象与核心编程机制
Java 面向对象与核心编程机制

系统讲解 Java 面向对象编程的核心知识体系,涵盖类的定义与封装、构造方法与 this/super 关键字、继承与方法重写、多态与向上向下转型、抽象类与接口的区别与设计原则、异常处理机制(try-catch-finally / 自定义异常)、泛型的类型参数与通配符、集合框架(List/Set/Map)的使用与遍历方式,帮助开发者全面掌握 Java 程序设计的核心机制与面向对象思维。

243

2026.04.17

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1818

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2884

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6204

2023.10.24

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

60

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn