简介
“封装记录”(Encapsulate Record)是一种重构手法,主要用于处理数据记录(如简单的结构体或数据类)。当直接使用数据记录时,数据的访问和修改缺乏控制,容易导致数据的不一致性和代码的可维护性降低。通过封装记录,可以隐藏数据的实现细节,提供统一的访问和修改接口,增强代码的安全性和可维护性。
针对的症状(代码坏味道)
- 数据直接暴露:记录中的数据字段直接被外部代码访问和修改,缺乏封装。
- 缺乏数据验证:外部代码可以随意修改数据,没有对数据的有效性进行验证。
- 代码耦合度高:外部代码依赖于记录的具体结构,当记录的结构发生变化时,需要修改大量的外部代码。
封装记录(Encapsulate Record)的详细步骤
- 识别记录结构
- 找出代码中使用的简单数据记录,这些记录通常是包含多个字段的类,且字段直接暴露给外部。
- 创建封装类
- 为记录创建一个封装类,将记录的字段声明为私有。
- 提供访问方法
- 为每个字段提供
getter方法,用于获取字段的值。 - 为需要修改的字段提供
setter方法,并在setter方法中添加数据验证逻辑。
- 为每个字段提供
- 替换原始记录使用
- 将所有直接访问记录字段的代码替换为调用封装类的
getter和setter方法。
- 将所有直接访问记录字段的代码替换为调用封装类的
- 测试
- 编译代码:确保代码编译通过,没有任何语法错误。
- 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
- 手动测试:如果有必要,进行手动测试以验证功能的正确性。
- 代码审查
- 同行评审:让同事或其他团队成员审查你的更改,确保代码质量和可维护性没有下降。
- 文档更新:如果项目有维护文档的习惯,记得更新相关文档,说明封装记录的影响。
示例
假设有一个简单的 Customer 记录,包含姓名和年龄字段,直接暴露给外部。
原始代码
public class Customer {
public String name;
public int age;
}
重构步骤
- 识别记录结构:
Customer类包含name和age字段,直接暴露给外部。 - 创建封装类:将字段声明为私有。
- 提供访问方法:为
name和age字段提供getter和setter方法,并在setter方法中添加数据验证逻辑。 - 替换原始记录使用:将所有直接访问
name和age字段的代码替换为调用getter和setter方法。
重构后代码
public class Customer {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
if (name != null && !name.isEmpty()) {
this.name = name;
} else {
throw new IllegalArgumentException("Name cannot be null or empty.");
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
throw new IllegalArgumentException("Age cannot be negative.");
}
}
}
练习
基础练习题
-
简单记录封装
-
给定以下 Java 代码,
Product类包含name和price字段,直接暴露。请封装该记录。public class Product { public String name; public double price; }
-
-
多字段记录封装
- 下面的 Java 代码中,
Employee类包含name、age和salary字段,直接暴露。请封装该记录。
- 下面的 Java 代码中,
public class Employee {
public String name;
public int age;
public double salary;
}
进阶练习题
-
记录封装与复杂验证逻辑
-
在这段 Java 代码中,
User类包含email和password字段,直接暴露。要求封装该记录,并在设置email时验证其格式,设置password时确保其长度不小于 6 位。public class User { public String email; public String password; }
-
-
记录封装与业务逻辑关联
- 给定以下 Java 代码,
Order类包含product、quantity和totalPrice字段,直接暴露。请封装该记录,并在设置quantity时更新totalPrice(假设product的价格已知)。
- 给定以下 Java 代码,
class Product {
private double price;
public Product(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
}
public class Order {
public Product product;
public int quantity;
public double totalPrice;
}
综合拓展练习题
- 多记录封装与代码审查模拟
-
考虑一个简单的 Java 图书馆系统,有
Book类和BorrowRecord类。Book类包含title、author和isAvailable字段,BorrowRecord类包含book、borrower和borrowDate字段,这些字段都直接暴露。请对这些记录进行 “封装记录” 重构。 -
假设你完成了重构,请模拟一份简单的代码审查报告,指出重构后的优点和可能存在的潜在问题。
import java.util.Date; public class Book { public String title; public String author; public boolean isAvailable; } public class BorrowRecord { public Book book; public String borrower; public Date borrowDate; }
-