重构第五章:重构的方法

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

复制代码
函数组合成类(Form Template Method): 多个函数具有相似的结构,可以将这些函数组合成一个类的方法,将原函数变为类的实例方法,以提高代码的可读性和维护性。
bash 复制代码
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): 当一个方法对另一个类的特性更感兴趣时,将该方法移到它所关心的类中,让这个类成为新方法的主体,以增强代码的内聚性。
bash 复制代码
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): 将字段移到其所关联的类中,以确保数据与其行为更为紧密地关联在一起,提高代码的一致性和可理解性。
bash 复制代码
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): 当一个类的一部分特性与其他部分不够相关时,可以创建一个新的子类,将相关的特性移入子类,以提高代码的清晰度和可维护性。
bash 复制代码
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): 当两个类有相似的特性时,可以创建一个新的超类,将相似的特性移到超类中,以避免重复的代码,提高代码的重用性。
bash 复制代码
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): 当子类仅仅使用父类的一部分功能时,可以使用委托,将子类中的方法调用委托给另一个拥有这部分功能的类,以减少类之间的耦合性。
bash 复制代码
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): 类似于上一个手法,但这次是替代整个子类而不是部分功能,通过委托来替代继承关系。
bash 复制代码
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): 当需要为某个类添加新功能时,可以创建一个新的子类或者使用委托来进行扩展,以避免修改原始类的代码。
bash 复制代码
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): 当无法修改某个类的代码时,可以通过创建一个新的类,然后在这个类中添加需要的方法,以实现对原始类的扩展。
bash 复制代码
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): 类似于引入本地扩展,但这里是引入本地的一段代码,将一些逻辑局部化,以提高代码的清晰度。
bash 复制代码
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): 移除一些不必要的设置函数,以确保对象的状态在创建后不可更改,提高代码的可靠性。
bash 复制代码
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): 当一个类委托给另一个类的时候,通过在调用端隐藏委托关系,以降低类之间的耦合度。
bash 复制代码
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): 当一个类只是委托了另一个类的所有方法时,可以移除中间人,直接调用最终的类的方法,以简化代码结构。
bash 复制代码
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): 当一个算法不再适用或者需要替换时,可以通过引入新的算法来替代原有的算法,以提高代码的灵活性。
bash 复制代码
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): 当一个条件表达式过于复杂时,可以将其拆分为多个较简单的条件,以提高代码的可读性和理解性。
bash 复制代码
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): 当多个条件表达式具有相同的结果时,可以将它们合并为一个条件表达式,以简化代码结构。
bash 复制代码
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): 当代码中存在相同的条件逻辑时,可以将重复的条件逻辑合并为一个条件,以减少重复代码。
bash 复制代码
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): 将复杂的条件表达式提炼成一个单独的函数或方法,以提高代码的可读性和可维护性。
bash 复制代码
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): 当多个异常处理块具有相同的代码时,可以将它们合并为一个异常处理块,以减少重复代码。
bash 复制代码
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): 在代码中引入断言,以确保程序在运行时的某个时刻满足某个条件,有助于提高代码的健壮性。
bash 复制代码
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): 当一个临时变量被赋值多次,可以将其拆分为多个临时变量,每个变量只负责一次赋值。
bash 复制代码
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): 当参数被函数内部赋值时,可以考虑移除这种赋值,以提高代码的清晰度。
bash 复制代码
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): 当一个临时变量的值是通过函数调用获取的,可以将其替换为函数调用,以减少临时变量的使用。
bash 复制代码
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): 当需要在运行时选择不同的函数时,可以引入函数对象,以提高代码的灵活性。
bash 复制代码
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): 当一个循环中处理多个逻辑时,可以拆分为多个循环,使每个循环只负责一种逻辑,提高代码的可读性。
bash 复制代码
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): 当循环中的每一步都是独立的时,可以使用管道操作来替代循环,提高代码的简洁性。
bash 复制代码
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): 当循环的逻辑可以通过递归来实现时,可以将循环替换为递归,以简化代码。
bash 复制代码
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): 当循环中涉及到集合的遍历时,可以使用迭代器来替代循环,提高代码的可读性。
bash 复制代码
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): 当一个函数负责两个不同阶段的逻辑时,可以拆分为两个函数,每个函数负责一个阶段的逻辑,以提高代码的模块化程度。
bash 复制代码
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): 移除不再被调用或者无用的代码,以减少代码库的冗余,提高代码的维护性。
bash 复制代码
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;
    }
}

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

相关推荐
松涛和鸣42 分钟前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
likangbinlxa1 小时前
【Oracle11g SQL详解】UPDATE 和 DELETE 操作的正确使用
数据库·sql
r i c k1 小时前
数据库系统学习笔记
数据库·笔记·学习
野犬寒鸦2 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习
雨中风华2 小时前
Linux, macOS系统实现远程目录访问(等同于windows平台xFsRedir软件的目录重定向)
linux·windows·macos
IvorySQL2 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·3 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德3 小时前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫3 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i3 小时前
完全卸载MariaDB
数据库·mariadb