在软件开发的舞台上,重构是一场不断进化的演变。为了优化、提升代码的质量,我们需要掌握各种重构的细致技法。以下是书中本章详细介绍的重构手法,它们为我们提供了一系列实践的方法,助力代码保持清晰、可读、可维护。
函数组合成类(Form Template Method): 多个函数具有相似的结构,可以将这些函数组合成一个类的方法,将原函数变为类的实例方法,以提高代码的可读性和维护性。
public class OrderProcessing {
public double calculateTotal(List<Item> items) {
// Calculate total logic
return 0.0;
}
public double applyDiscount(double total) {
// Apply discount logic
return 0.0;
}
}
函数移动(Move Method): 当一个方法对另一个类的特性更感兴趣时,将该方法移到它所关心的类中,让这个类成为新方法的主体,以增强代码的内聚性。
public class Account {
public double overdraftCharge() {
// Overdraft charge logic
return 0.0;
}
}
public class AccountType {
public double overdraftCharge() {
// Overdraft charge logic moved to AccountType
return 0.0;
}
}
字段移动(Move Field): 将字段移到其所关联的类中,以确保数据与其行为更为紧密地关联在一起,提高代码的一致性和可理解性。
public class Customer {
private String name;
}
public class Address {
private String city;
private String state;
}
// Move 'city' and 'state' fields from Customer to Address
提炼子类(Extract Subclass): 当一个类的一部分特性与其他部分不够相关时,可以创建一个新的子类,将相关的特性移入子类,以提高代码的清晰度和可维护性。
public class JobPosition {
private String title;
private double salary;
// Constructors and methods
}
public class ManagerPosition extends JobPosition {
private double bonus;
// Constructors and methods
}
提炼超类(Extract Superclass): 当两个类有相似的特性时,可以创建一个新的超类,将相似的特性移到超类中,以避免重复的代码,提高代码的重用性。
public class Bird {
private String name;
// Constructors and methods
}
public class Sparrow extends Bird {
// Additional attributes and methods specific to Sparrow
}
以委托取代继承(Replace Inheritance with Delegation): 当子类仅仅使用父类的一部分功能时,可以使用委托,将子类中的方法调用委托给另一个拥有这部分功能的类,以减少类之间的耦合性。
public class Printer {
public void print(String content) {
// Print content logic
}
}
public class Document {
private Printer printer;
public void printDocument(String content) {
printer.print(content);
}
}
以委托取代子类(Replace Subclass with Delegation): 类似于上一个手法,但这次是替代整个子类而不是部分功能,通过委托来替代继承关系。
public interface Engine {
void start();
}
public class CarEngine implements Engine {
@Override
public void start() {
// Car engine start logic
}
}
public class BoatEngine implements Engine {
private final CarEngine carEngine;
public BoatEngine(CarEngine carEngine) {
this.carEngine = carEngine;
}
@Override
public void start() {
// Delegating to CarEngine
carEngine.start();
}
}
引入本地扩展(Introduce Local Extension): 当需要为某个类添加新功能时,可以创建一个新的子类或者使用委托来进行扩展,以避免修改原始类的代码。
public class DateUtils {
public static Date addDaysToDate(Date date, int days) {
// Add days to date logic
return new Date();
}
}
// Client code
Date newDate = DateUtils.addDaysToDate(oldDate, 5);
引入外加函数(Introduce Foreign Method): 当无法修改某个类的代码时,可以通过创建一个新的类,然后在这个类中添加需要的方法,以实现对原始类的扩展。
public class StringUtils {
public static String reverse(String input) {
// Reverse string logic
return new StringBuilder(input).reverse().toString();
}
}
// Client code
String reversed = StringUtils.reverse("hello");
引入本地代码(Introduce Local Procedure): 类似于引入本地扩展,但这里是引入本地的一段代码,将一些逻辑局部化,以提高代码的清晰度。
public class Calculator {
public int add(int a, int b) {
// Addition logic
return a + b;
}
}
// Client code
Calculator calculator = new Calculator();
int result = calculator.add(5, 3);
移除设置函数(Remove Setting Method): 移除一些不必要的设置函数,以确保对象的状态在创建后不可更改,提高代码的可靠性。
public class ImmutablePerson {
private final String name;
public ImmutablePerson(String name) {
this.name = name;
}
// Removed setting method
}
// Client code
ImmutablePerson person = new ImmutablePerson("John");
隐藏委托关系(Hide Delegate): 当一个类委托给另一个类的时候,通过在调用端隐藏委托关系,以降低类之间的耦合度。
public class Department {
private final Employee supervisor;
public Department(Employee supervisor) {
this.supervisor = supervisor;
}
// Hide delegate
public String getSupervisorName() {
return supervisor.getName();
}
}
public class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
移除中间人(Remove Middle Man): 当一个类只是委托了另一个类的所有方法时,可以移除中间人,直接调用最终的类的方法,以简化代码结构。
public class Manager {
private final Employee employee;
public Manager(Employee employee) {
this.employee = employee;
}
// Remove middle man
public String getEmployeeName() {
return employee.getName();
}
}
// Client code
Employee employee = new Employee("Alice");
Manager manager = new Manager(employee);
String employeeName = manager.getEmployeeName();
替换算法(Replace Algorithm): 当一个算法不再适用或者需要替换时,可以通过引入新的算法来替代原有的算法,以提高代码的灵活性。
public interface SortingAlgorithm {
int[] sort(int[] array);
}
public class BubbleSort implements SortingAlgorithm {
@Override
public int[] sort(int[] array) {
// Bubble sort logic
return array;
}
}
// Client code
SortingAlgorithm sortingAlgorithm = new BubbleSort();
int[] sortedArray = sortingAlgorithm.sort(new int[]{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5});
解除混淆(Decompose Conditional): 当一个条件表达式过于复杂时,可以将其拆分为多个较简单的条件,以提高代码的可读性和理解性。
public class LoanApproval {
public boolean isLoanApproved(double creditScore, double income) {
// Decompose conditional
return hasGoodCredit(creditScore) && hasSufficientIncome(income);
}
private boolean hasGoodCredit(double creditScore) {
// Check credit score logic
return creditScore > 700;
}
private boolean hasSufficientIncome(double income) {
// Check income logic
return income > 50000;
}
}
合并条件表达式(Consolidate Conditional Expression): 当多个条件表达式具有相同的结果时,可以将它们合并为一个条件表达式,以简化代码结构。
public class DiscountCalculator {
public double calculateDiscount(double totalAmount, int loyaltyPoints) {
// Consolidate conditional expression
if (totalAmount > 100 && loyaltyPoints > 50) {
return totalAmount * 0.2;
} else {
return 0;
}
}
}
合并重复的条件片段(Consolidate Duplicate Conditional Fragments): 当代码中存在相同的条件逻辑时,可以将重复的条件逻辑合并为一个条件,以减少重复代码。
public class ReportGenerator {
public void generateReport(boolean isWeekend) {
// Consolidate duplicate conditional fragments
if (isWeekend) {
performWeekendLogic();
} else {
performWeekdayLogic();
}
}
private void performWeekendLogic() {
// Weekend logic
}
private void performWeekdayLogic() {
// Weekday logic
}
}
提炼条件表达式(Extract Conditional Expression): 将复杂的条件表达式提炼成一个单独的函数或方法,以提高代码的可读性和可维护性。
public class TemperatureChecker {
public String checkTemperature(int temperature) {
// Extract conditional expression
return isHighTemperature(temperature) ? "Too hot" : "Comfortable";
}
private boolean isHighTemperature(int temperature) {
// Check high temperature logic
return temperature > 30;
}
}
合并异常(Consolidate Duplicate Conditional Fragments): 当多个异常处理块具有相同的代码时,可以将它们合并为一个异常处理块,以减少重复代码。
public class ErrorHandler {
public void handleException(Exception exception) {
// Consolidate duplicate conditional fragments
if (exception instanceof IOException) {
logIOException((IOException) exception);
} else if (exception instanceof SQLException) {
logSQLException((SQLException) exception);
}
}
private void logIOException(IOException ioException) {
// Log IOException
}
private void logSQLException(SQLException sqlException) {
// Log SQLException
}
}
引入断言(Introduce Assertion): 在代码中引入断言,以确保程序在运行时的某个时刻满足某个条件,有助于提高代码的健壮性。
public class AgeValidator {
public boolean isValidAge(int age) {
// Introduce assertion
assert age >= 0 : "Age should be non-negative";
return age >= 18 && age <= 65;
}
}
分解临时变量(Split Temporary Variable): 当一个临时变量被赋值多次,可以将其拆分为多个临时变量,每个变量只负责一次赋值。
public class CircleCalculator {
public double calculateCircleArea(double radius) {
// Split temporary variable
double circumference = 2 * Math.PI * radius;
double area = Math.PI * Math.pow(radius, 2);
return area;
}
}
移除对参数的赋值(Remove Assignment to Parameter): 当参数被函数内部赋值时,可以考虑移除这种赋值,以提高代码的清晰度。
public class ParameterModifier {
public void modifyParameter(int[] numbers) {
// Remove assignment to parameter
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[i] * 2;
}
}
}
以查询取代临时变量(Replace Temp with Query): 当一个临时变量的值是通过函数调用获取的,可以将其替换为函数调用,以减少临时变量的使用。
public class PriceCalculator {
private double basePrice;
private double discount;
public double calculateFinalPrice() {
// Replace temp with query
return getBasePrice() * (1 - getDiscount());
}
private double getBasePrice() {
// Get base price logic
return basePrice;
}
private double getDiscount() {
// Get discount logic
return discount;
}
}
以函数对象取代函数(Replace Function with Function Pointer): 当需要在运行时选择不同的函数时,可以引入函数对象,以提高代码的灵活性。
public interface MathOperation {
int operate(int a, int b);
}
public class Addition implements MathOperation {
@Override
public int operate(int a, int b) {
return a + b;
}
}
// Client code
MathOperation addition = new Addition();
int result = addition.operate(5, 3);
拆分循环(Split Loop): 当一个循环中处理多个逻辑时,可以拆分为多个循环,使每个循环只负责一种逻辑,提高代码的可读性。
public class NumberProcessor {
public void processNumbers(int[] numbers) {
// Split loop
for (int number : numbers) {
processEvenNumber(number);
}
for (int number : numbers) {
processOddNumber(number);
}
}
private void processEvenNumber(int number) {
// Process even number logic
}
private void processOddNumber(int number) {
// Process odd number logic
}
}
以管道取代循环(Replace Loop with Pipeline): 当循环中的每一步都是独立的时,可以使用管道操作来替代循环,提高代码的简洁性。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StringProcessor {
public List<String> processStrings(List<String> strings) {
// Replace loop with pipeline
return strings.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
}
}
以递归取代循环(Replace Loop with Recursion): 当循环的逻辑可以通过递归来实现时,可以将循环替换为递归,以简化代码。
public class FactorialCalculator {
public int calculateFactorial(int n) {
// Replace loop with recursion
if (n <= 1) {
return 1;
} else {
return n * calculateFactorial(n - 1);
}
}
}
以迭代器取代循环(Replace Loop with Iterator): 当循环中涉及到集合的遍历时,可以使用迭代器来替代循环,提高代码的可读性。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListProcessor {
public void processList(List<String> strings) {
// Replace loop with iterator
Iterator<String> iterator = strings.iterator();
while (iterator.hasNext()) {
String current = iterator.next();
processString(current);
}
}
private void processString(String string) {
// Process string logic
}
}
拆分阶段(Split Phase): 当一个函数负责两个不同阶段的逻辑时,可以拆分为两个函数,每个函数负责一个阶段的逻辑,以提高代码的模块化程度。
public class PaymentProcessor {
public void processPayment(String paymentMethod, double amount) {
// Split phase
if ("CreditCard".equals(paymentMethod)) {
processCreditCardPayment(amount);
} else if ("PayPal".equals(paymentMethod)) {
processPayPalPayment(amount);
}
}
private void processCreditCardPayment(double amount) {
// Process credit card payment logic
}
private void processPayPalPayment(double amount) {
// Process PayPal payment logic
}
}
移除死代码(Remove Dead Code): 移除不再被调用或者无用的代码,以减少代码库的冗余,提高代码的维护性。
public class DeadCodeRemover {
public void process() {
// Remove dead code
int result = calculateResult(5, 3);
System.out.println(result);
}
private int calculateResult(int a, int b) {
// Dead code
return a * b;
}
}
每个手法都有其特定的应用场景,我们可以根据实际情况选择合适的手法进行应用~~~~~太多了,就当笔记吧,散会