重构第五章:重构的方法

发布时间:2023年12月17日

在软件开发的舞台上,重构是一场不断进化的演变。为了优化、提升代码的质量,我们需要掌握各种重构的细致技法。以下是书中本章详细介绍的重构手法,它们为我们提供了一系列实践的方法,助力代码保持清晰、可读、可维护。

函数组合成类(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;
    }
}

每个手法都有其特定的应用场景,我们可以根据实际情况选择合适的手法进行应用~~~~~太多了,就当笔记吧,散会

文章来源:https://blog.csdn.net/qq_44444470/article/details/134809712
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。