代码重构的15个小技巧

在这篇文章中,我们探讨了15个代码重构的小技巧,从简单的提取方法到高级的设计模式应用。这些技巧可以帮助我们写出更加简洁、可读、可维护的代码。代码重构是一个持续的过程,我们应该在日常开发中不断地应用这些技巧,逐步改进我们的代码质量。

前言

相信很多小伙伴在日常工作中都会遇到这样的情况:接手了一个历史项目,代码像一团乱麻。

或者自己写的代码随着业务的不断迭代,变得越来越臃肿难以维护。

这时候,代码重构就显得尤为重要了。

那么,如何进行高效的代码重构呢?

这篇文章我跟大家大家一起聊聊15个实用的代码重构技巧,希望对你会有所帮助。

1. 提取方法

有些小伙伴在工作中可能会写出这样的代码:一个方法几百行,里面包含了各种业务逻辑。

这样的代码不仅难以阅读,也难以维护和测试。

重构前:

复制

public void processOrder(Order order) {
    // 验证订单
    if (order == null) {
        throw new IllegalArgumentException("订单不能为空");
    }
    if (order.getItems() == null || order.getItems().isEmpty()) {
        throw new IllegalArgumentException("订单项不能为空");
    }
    if (order.getCustomer() == null) {
        throw new IllegalArgumentException("客户信息不能为空");
    }
    
    // 计算订单总价
    double total = 0;
    for (OrderItem item : order.getItems()) {
        double price = item.getPrice();
        int quantity = item.getQuantity();
        total += price * quantity;
    }
    
    // 应用折扣
    if (order.getCustomer().isVip()) {
        total = total * 0.9;
    }
    
    // 保存订单
    order.setTotal(total);
    orderRepository.save(order);
    
    // 发送通知
    String message = "订单" + order.getId() + "已处理,总价:" + 
    total;
    emailService.sendEmail(order.getCustomer().getEmail(), "订单处理
    通知", message);
    smsService.sendSms(order.getCustomer().getPhone(), message);
}

重构后:

public void processOrder(Order order) {
    validateOrder(order);
    double total = calculateOrderTotal(order);
    total = applyDiscount(order, total);
    saveOrder(order, total);
    sendNotifications(order, total);
}

private void validateOrder(Order order) {
    if (order == null) {
        thrownew IllegalArgumentException("订单不能为空");
    }
    if (order.getItems() == null || order.getItems().isEmpty()) {
        thrownew IllegalArgumentException("订单项不能为空");
    }
    if (order.getCustomer() == null) {
        thrownew IllegalArgumentException("客户信息不能为空");
    }
}

private double calculateOrderTotal(Order order) {
    double total = 0;
    for (OrderItem item : order.getItems()) {
        double price = item.getPrice();
        int quantity = item.getQuantity();
        total += price * quantity;
    }
    return total;
}

private double applyDiscount(Order order, double total) {
    if (order.getCustomer().isVip()) {
        return total * 0.9;
    }
    return total;
}

private void saveOrder(Order order, double total) {
    order.setTotal(total);
    orderRepository.save(order);
}

private void sendNotifications(Order order, double total) {
    String message = "订单" + order.getId() + "已处理,总价:" + 
    total;
    emailService.sendEmail(order.getCustomer().getEmail(), "订单处理
    通知", message);
    smsService.sendSms(order.getCustomer().getPhone(), message);
}

通过提取方法,我们将一个大方法拆分成了多个小方法,每个方法只负责一个功能。

这样不仅提高了代码的可读性,也使得每个方法更容易测试和维护。

2. 引入解释性变量

有时候,一个复杂的表达式可能难以理解。

这时,我们可以引入一个解释性变量来提高代码的可读性。

重构前:

public boolean isEligibleForDiscount(Customer customer, Order 
order) {
    return (customer.getAge() >= 60 || (customer.getMembershipYears
    () > 5 && order.getTotal() > 1000)) && !customer.
    hasOutstandingPayments();
}

重构后:

public boolean isEligibleForDiscount(Customer customer, Order 
order) {
    boolean isSenior = customer.getAge() >= 60;
    boolean isLoyalCustomerWithLargeOrder = customer.
    getMembershipYears() > 5 && order.getTotal() > 1000;
    boolean hasNoOutstandingPayments = !customer.
    hasOutstandingPayments();
    
    return (isSenior || isLoyalCustomerWithLargeOrder) && 
    hasNoOutstandingPayments;
}

通过引入解释性变量,我们使得复杂的条件表达式更加清晰易懂。每个变量都有一个描述性的名称,使得代码的意图更加明确。

3. 替换条件表达式

有些小伙伴在处理不同类型的对象时,可能会使用大量的条件语句(if-else或switch)。

这样的代码不仅冗长,而且每次添加新类型都需要修改这些条件语句,违反了开闭原则。

重构前:

public class PaymentProcessor {
    public void processPayment(Payment payment) {
        if (payment.getType().equals("CREDIT_CARD")) {
            // 处理信用卡支付
            validateCreditCard(payment);
            chargeCreditCard(payment);
        } else if (payment.getType().equals("PAYPAL")) {
            // 处理PayPal支付
            validatePayPalAccount(payment);
            chargePayPalAccount(payment);
        } else if (payment.getType().equals("BANK_TRANSFER")) {
            // 处理银行转账
            validateBankAccount(payment);
            initiateTransfer(payment);
        } else {
            throw new IllegalArgumentException("不支持的支付类型:" + 
            payment.getType());
        }
    }
    
    // 其他方法...
}

重构后:

public interface PaymentProcessor {
    void processPayment(Payment payment);
}

public class CreditCardProcessor implements PaymentProcessor {
    @Override
    public void processPayment(Payment payment) {
        validateCreditCard(payment);
        chargeCreditCard(payment);
    }
    
    // 其他方法...
}

public class PayPalProcessor implements PaymentProcessor {
    @Override
    public void processPayment(Payment payment) {
        validatePayPalAccount(payment);
        chargePayPalAccount(payment);
    }
    
    // 其他方法...
}

public class BankTransferProcessor implements PaymentProcessor {
    @Override
    public void processPayment(Payment payment) {
        validateBankAccount(payment);
        initiateTransfer(payment);
    }
    
    // 其他方法...
}

public class PaymentFactory {
    public static PaymentProcessor getProcessor(String paymentType) 
    {
        if (paymentType.equals("CREDIT_CARD")) {
            return new CreditCardProcessor();
        } elseif (paymentType.equals("PAYPAL")) {
            return new PayPalProcessor();
        } elseif (paymentType.equals("BANK_TRANSFER")) {
            return new BankTransferProcessor();
        } else {
            throw new IllegalArgumentException("不支持的支付类型:" + 
            paymentType);
        }
    }
}

// 使用
PaymentProcessor processor = PaymentFactory.getProcessor(payment.
getType());
processor.processPayment(payment);

通过使用多态,我们将不同类型的支付处理逻辑分散到各自的类中,使得代码更加模块化,也更容易扩展。

当需要添加新的支付类型时,只需创建一个新的处理器类,而不需要修改现有的代码。

4. 移除重复代码

代码重复是软件开发中的一大问题。

重复的代码不仅增加了代码量,也增加了维护的难度。当需要修改一个功能时,可能需要在多个地方进行相同的修改,这增加了出错的可能性。

重构前:

public class UserService {
    public User findUserById(Long id) {
        // 记录日志
        Logger logger = LoggerFactory.getLogger(UserService.class);
        logger.info("查询用户,ID:" + id);
        
        // 查询用户
        User user = userRepository.findById(id);
        if (user == null) {
            logger.error("用户不存在,ID:" + id);
            thrownew UserNotFoundException("用户不存在,ID:" + id);
        }
        
        return user;
    }
    
    public User findUserByEmail(String email) {
        // 记录日志
        Logger logger = LoggerFactory.getLogger(UserService.class);
        logger.info("查询用户,Email:" + email);
        
        // 查询用户
        User user = userRepository.findByEmail(email);
        if (user == null) {
            logger.error("用户不存在,Email:" + email);
            thrownew UserNotFoundException("用户不存在,Email:" + 
            email);
        }
        
        return user;
    }
}

重构后:

public class UserService {
    private static final Logger logger = LoggerFactory.getLogger
    (UserService.class);
    
    public User findUserById(Long id) {
        logger.info("查询用户,ID:" + id);
        return findUserOrThrow(() -> userRepository.findById(id), "
        用户不存在,ID:" + id);
    }
    
    public User findUserByEmail(String email) {
        logger.info("查询用户,Email:" + email);
        return findUserOrThrow(() -> userRepository.findByEmail
        (email), "用户不存在,Email:" + email);
    }
    
    private User findUserOrThrow(Supplier<User> finder, String 
    errorMessage) {
        User user = finder.get();
        if (user == null) {
            logger.error(errorMessage);
            throw new UserNotFoundException(errorMessage);
        }
        return user;
    }
}

通过提取公共方法,我们消除了重复代码,使得代码更加简洁。

当需要修改查询用户的逻辑时,只需要修改一个地方,而不是多个地方。

5. 引入参数对象

当一个方法有多个参数时,特别是当这些参数经常一起出现时,可以考虑将它们封装成一个对象。

重构前:

public class ReportGenerator {
    public Report generateReport(String startDate, String endDate, 
    String department, String format, boolean includeCharts) {
        // 生成报告的逻辑
        // ...
    }
    
    public void emailReport(String startDate, String endDate, 
    String department, String format, boolean includeCharts, String 
    email) {
        Report report = generateReport(startDate, endDate, 
        department, format, includeCharts);
        // 发送报告的逻辑
        // ...
    }
    
    public void saveReport(String startDate, String endDate, String 
    department, String format, boolean includeCharts, String 
    filePath) {
        Report report = generateReport(startDate, endDate, 
        department, format, includeCharts);
        // 保存报告的逻辑
        // ...
    }
}

重构后:

public class ReportCriteria {
    private String startDate;
    private String endDate;
    private String department;
    private String format;
    private boolean includeCharts;
    
    // 构造函数、getter和setter
    // ...
}

public class ReportGenerator {
    public Report generateReport(ReportCriteria criteria) {
        // 生成报告的逻辑
        // ...
    }
    
    public void emailReport(ReportCriteria criteria, String email) {
        Report report = generateReport(criteria);
        // 发送报告的逻辑
        // ...
    }
    
    public void saveReport(ReportCriteria criteria, String 
    filePath) {
        Report report = generateReport(criteria);
        // 保存报告的逻辑
        // ...
    }
}

通过引入参数对象,我们减少了方法的参数数量,使得方法调用更加简洁。同时,参数对象也可以包含与这些参数相关的行为,进一步提高代码的内聚性。

6. 使用策略模式

有些小伙伴在处理不同的算法或策略时,可能会使用大量的条件语句。

这样的代码不仅难以维护,也难以扩展。

重构前:

public class ShippingCalculator {
    public double calculateShippingCost(Order order, String 
    shippingMethod) {
        if (shippingMethod.equals("STANDARD")) {
            // 标准运费计算逻辑
            return order.getWeight() * 0.5;
        } else if (shippingMethod.equals("EXPRESS")) {
            // 快递运费计算逻辑
            return order.getWeight() * 1.0 + 10;
        } else if (shippingMethod.equals("OVERNIGHT")) {
            // 隔夜运费计算逻辑
            return order.getWeight() * 1.5 + 20;
        } else {
            throw new IllegalArgumentException("不支持的运输方式:" + 
            shippingMethod);
        }
    }
}

重构后:

public interface ShippingStrategy {
    double calculateShippingCost(Order order);
}

public class StandardShipping implements ShippingStrategy {
    @Override
    public double calculateShippingCost(Order order) {
        return order.getWeight() * 0.5;
    }
}

public class ExpressShipping implements ShippingStrategy {
    @Override
    public double calculateShippingCost(Order order) {
        return order.getWeight() * 1.0 + 10;
    }
}

public class OvernightShipping implements ShippingStrategy {
    @Override
    public double calculateShippingCost(Order order) {
        return order.getWeight() * 1.5 + 20;
    }
}

public class ShippingCalculator {
    private Map<String, ShippingStrategy> strategies = new HashMap<>
    ();
    
    public ShippingCalculator() {
        strategies.put("STANDARD", new StandardShipping());
        strategies.put("EXPRESS", new ExpressShipping());
        strategies.put("OVERNIGHT", new OvernightShipping());
    }
    
    public double calculateShippingCost(Order order, String 
    shippingMethod) {
        ShippingStrategy strategy = strategies.get(shippingMethod);
        if (strategy == null) {
            thrownew IllegalArgumentException("不支持的运输方式:" + 
            shippingMethod);
        }
        return strategy.calculateShippingCost(order);
    }
}

通过使用策略模式,我们将不同的运费计算逻辑分散到各自的类中,使得代码更加模块化,也更容易扩展。

当需要添加新的运输方式时,只需创建一个新的策略类,并将其添加到策略映射中,而不需要修改现有的代码。

7. 使用构建者模式

当一个类有多个构造参数时,特别是当有些参数是可选的时,可以考虑使用构建者模式。

重构前:

复制

public class User {
    private String username;
    private String email;
    private String firstName;
    private String lastName;
    private String phone;
    private String address;
    private String city;
    private String country;
    private String postalCode;
    
    // 构造函数
    public User(String username, String email) {
        this.username = username;
        this.email = email;
    }
    
    public User(String username, String email, String firstName, 
    String lastName) {
        this.username = username;
        this.email = email;
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    public User(String username, String email, String firstName, 
    String lastName, String phone) {
        this.username = username;
        this.email = email;
        this.firstName = firstName;
        this.lastName = lastName;
        this.phone = phone;
    }
    
    // 更多构造函数...
    
    // getter和setter
    // ...
}

重构后:

public class User {
    private String username;
    private String email;
    private String firstName;
    private String lastName;
    private String phone;
    private String address;
    private String city;
    private String country;
    private String postalCode;
    
    private User(Builder builder) {
        this.username = builder.username;
        this.email = builder.email;
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.phone = builder.phone;
        this.address = builder.address;
        this.city = builder.city;
        this.country = builder.country;
        this.postalCode = builder.postalCode;
    }
    
    // getter(没有setter,使对象不可变)
    // ...
    
    public static class Builder {
        // 必需参数
        private final String username;
        private final String email;
        
        // 可选参数
        private String firstName;
        private String lastName;
        private String phone;
        private String address;
        private String city;
        private String country;
        private String postalCode;
        
        public Builder(String username, String email) {
            this.username = username;
            this.email = email;
        }
        
        public Builder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        } 
        
        public Builder lastName(String lastName) {
            this.lastName = lastName;
            return this;
        }
         
        public Builder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public Builder address(String address) {
            this.address = address;
            return this;
        }
        
        public Builder city(String city) {
            this.city = city;
            returnthis;
        }
        
        public Builder country(String country) {
            this.c ountry = country;
            return this;
        }
        
        public Builder postalCode(String postalCode) {
            this.postalCode = postalCode;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

// 使用
User user = new User.Builder("johndoe", "john.doe@example.com")
    .firstName("John")
    .lastName("Doe")
    .phone("1234567890")
    .build();

通过使用构建者模式,我们解决了构造函数参数过多的问题,使得对象创建更加灵活和可读。

同时,构建者模式也可以确保对象在创建后是不可变的,提高了代码的安全性。

8. 使用工厂方法

当对象的创建逻辑比较复杂时,可以考虑使用工厂方法。

重构前:

public class ProductService {
    public Product createProduct(String type, String name, double 
    price) {
        Product product;
        if (type.equals("PHYSICAL")) {
            product = new PhysicalProduct(name, price);
            // 设置物理产品的属性
            // ...
        } else if (type.equals("DIGITAL")) {
            product = new DigitalProduct(name, price);
            // 设置数字产品的属性
            // ...
        } else if (type.equals("SUBSCRIPTION")) {
            product = new SubscriptionProduct(name, price);
            // 设置订阅产品的属性
            // ...
        } else {
            throw new IllegalArgumentException("不支持的产品类型:" + 
            type);
        }
        return product;
    }
}

重构后:

public abstract class ProductFactory {
    public static Product createProduct(String type, String name, 
    double price) {
        if (type.equals("PHYSICAL")) {
            return createPhysicalProduct(name, price);
        } else if (type.equals("DIGITAL")) {
            return createDigitalProduct(name, price);
        } else if (type.equals("SUBSCRIPTION")) {
            return createSubscriptionProduct(name, price);
        } else {
            thrownew IllegalArgumentException("不支持的产品类型:" + 
            type);
        }
    }
    
    private static Product createPhysicalProduct(String name, 
    double price) {
        PhysicalProduct product = new PhysicalProduct(name, price);
        // 设置物理产品的属性
        // ...
        return product;
    }
    
    private static Product createDigitalProduct(String name, double 
    price) {
        DigitalProduct product = new DigitalProduct(name, price);
        // 设置数字产品的属性
        // ...
        return product;
    }
    
    private static Product createSubscriptionProduct(String name, 
    double price) {
        SubscriptionProduct product = new SubscriptionProduct(name, 
        price);
        // 设置订阅产品的属性
        // ...
        return product;
    }
}

// 使用
Product product = ProductFactory.createProduct("PHYSICAL", "书籍", 
29.99);

通过使用工厂方法,我们将对象的创建逻辑从客户端代码中分离出来,使得代码更加模块化,也更容易维护。

当需要添加新的产品类型时,只需在工厂类中添加相应的创建方法,而不需要修改客户端代码。

9. 使用Optional避免空指针异常

空指针异常(NullPointerException)是Java中最常见的异常之一。

为了避免这种异常,我们可以使用Java 8引入的Optional类。

重构前:

public class UserService {
    public User findUserById(Long id) {
        // 查询用户
        return userRepository.findById(id);
    }
    
    public String getUserEmail(Long id) {
        User user = findUserById(id);
        if (user != null) {
            String email = user.getEmail();
            if (email != null) {
                return email;
            }
        }
        return"未知";
    }
}
    public class UserService {
        public Optional<User> findUserById(Long id) {
            // 查询用户
            User user = userRepository.findById(id);
            return Optional.ofNullable(user);
        }
        
        public String getUserEmail(Long id) {
            return findUserById(id)
                .map(User::getEmail)
                .orElse("未知");
        }
    }

    通过使用Optional,我们明确表示方法可能返回空值,使得代码更加清晰。

    同时,Optional提供了丰富的API,如map、filter、orElse等,使得处理可能为空的值更加方便。

    10. 使用Stream API简化集合操作

    Java 8引入的Stream API提供了一种函数式编程的方式来处理集合,使得代码更加简洁和可读。

    重构前:

    public class OrderService {
        public List<Order> findLargeOrders(List<Order> orders) {
            List<Order> largeOrders = new ArrayList<>();
            for (Order order : orders) {
                if (order.getTotal() > 1000) {
                    largeOrders.add(order);
                }
            }
            return largeOrders;
        }
        
        public double calculateTotalRevenue(List<Order> orders) {
            double total = 0;
            for (Order order : orders) {
                total += order.getTotal();
            }
            return total;
        }
        
        public List<String> getCustomerNames(List<Order> orders) {
            List<String> names = new ArrayList<>();
            for (Order order : orders) {
                String name = order.getCustomer().getName();
                if (!names.contains(name)) {
                    names.add(name);
                }
            }
            return names;
        }
    }

    重构后:

    public class OrderService {
        public List<Order> findLargeOrders(List<Order> orders) {
            return orders.stream()
                .filter(order -> order.getTotal() > 1000)
                .collect(Collectors.toList());
        }
        
        public double calculateTotalRevenue(List<Order> orders) {
            return orders.stream()
                .mapToDouble(Order::getTotal)
                .sum();
        }
        
        public List<String> getCustomerNames(List<Order> orders) {
            return orders.stream()
                .map(order -> order.getCustomer().getName())
                .distinct()
                .collect(Collectors.toList());
        }
    }

    通过使用Stream API,我们将命令式的代码转换为声明式的代码,使得代码更加简洁和可读。

    Stream API提供了丰富的操作,如filter、map、reduce等,使得处理集合更加方便。

    11. 使用Lambda表达式简化匿名内部类

    Java 8引入的Lambda表达式提供了一种更简洁的方式来创建匿名函数,特别适合用于替代匿名内部类。

    重构前:

    public class ButtonHandler {
        public void setupButton(Button button) {
            button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    // 处理点击事件
                    System.out.println("按钮被点击");
                }
            });
        }
        
        public void sortUsers(List<User> users) {
            Collections.sort(users, new Comparator<User>() {
                @Override
                public int compare(User u1, User u2) {
                    return u1.getName().compareTo(u2.getName());
                }
            });
        }
    }

    重构后:

    public class ButtonHandler {
        public void setupButton(Button button) {
            button.setOnClickListener(view -> {
                // 处理点击事件
                System.out.println("按钮被点击");
            });
        }
        
        public void sortUsers(List<User> users) {
            Collections.sort(users, (u1, u2) -> u1.getName().compareTo
            (u2.getName()));
            // 或者更简洁地
            users.sort(Comparator.comparing(User::getName));
        }
    }

    通过使用Lambda表达式,我们将冗长的匿名内部类替换为简洁的函数式表达式,使得代码更加简洁和可读。

    12. 使用方法引用简化Lambda表达式

    Java 8引入的方法引用提供了一种更简洁的方式来引用已有的方法,特别适合用于替代简单的Lambda表达式。

    重构前:

    public class UserProcessor {
        public List<String> getUserNames(List<User> users) {
            return users.stream()
                .map(user -> user.getName())
                .collect(Collectors.toList());
        }
        
        public void printUsers(List<User> users) {
            users.forEach(user -> System.out.println(user));
        }
        
        public List<User> createUsers(List<String> names) {
            return names.stream()
                .map(name -> new User(name))
                .collect(Collectors.toList());
        }
    }

    重构后:

    public class UserProcessor {
        public List<String> getUserNames(List<User> users) {
            return users.stream()
                .map(User::getName)
                .collect(Collectors.toList());
        }
        
        public void printUsers(List<User> users) {
            users.forEach(System.out::println);
        }
        
        public List<User> createUsers(List<String> names) {
            return names.stream()
                .map(User::new)
                .collect(Collectors.toList());
        }
    }

    通过使用方法引用,我们将简单的Lambda表达式替换为更简洁的方法引用,使得代码更加简洁和可读。

    13. 使用CompletableFuture简化异步编程

    Java 8引入的CompletableFuture提供了一种更简洁的方式来处理异步操作,特别适合用于替代传统的回调方式。

    重构前:

    public class UserService {
        public void processUser(Long userId, Callback<User> callback) {
            // 异步查询用户
            userRepository.findByIdAsync(userId, new Callback<User>() {
                @Override
                public void onSuccess(User user) {
                    // 异步查询用户的订单
                    orderRepository.findByUserIdAsync(userId, new
                    Callback<List<Order>>() {
                        @Override
                        public void onSuccess(List<Order> orders) {
                            // 处理用户和订单
                            user.setOrders(orders);
                            callback.onSuccess(user);
                        }
                        
                        @Override
                        public void onError(Exception e) {
                            callback.onError(e);
                        }
                    });
                }
                
                @Override
                public void onError(Exception e) {
                    callback.onError(e);
                }
            });
        }
    }

    重构后:

    public class UserService {
        public CompletableFuture<User> processUser(Long userId) {
            return userRepository.findByIdAsync(userId)
                .thenCompose(user -> orderRepository.findByUserIdAsync
                (userId)
                    .thenApply(orders -> {
                        user.setOrders(orders);
                        return user;
                    }));
        }
    }
    
    // 使用
    userService.processUser(123L)
        .thenAccept(user -> {
            // 处理用户
            System.out.println("用户:" + user.getName());
            System.out.println("订单数:" + user.getOrders().size());
        })
        .exceptionally(e -> {
            // 处理异常
            System.err.println("处理用户时出错:" + e.getMessage());
            returnnull;
        });

    通过使用CompletableFuture,我们将嵌套的回调转换为链式的调用,使得代码更加简洁和可读。

    CompletableFuture提供了丰富的API,如thenApply、thenCompose、thenAccept等,使得处理异步操作更加方便。

    14. 使用接口默认方法简化接口实现

    Java 8引入的接口默认方法允许在接口中提供方法的默认实现,使得接口的演化更加灵活。

    重构前:

    public interface PaymentProcessor {
        void processPayment(Payment payment);
        void refundPayment(Payment payment);
        void cancelPayment(Payment payment);
    }
    
    public class CreditCardProcessor implements PaymentProcessor {
        @Override
        public void processPayment(Payment payment) {
            // 处理信用卡支付
        }
        
        @Override
        public void refundPayment(Payment payment) {
            // 处理信用卡退款
        }
        
        @Override
        public void cancelPayment(Payment payment) {
            // 取消支付并退款
            refundPayment(payment);
        }
    }
    
    public class PayPalProcessor implements PaymentProcessor {
        @Override
        public void processPayment(Payment payment) {
            // 处理PayPal支付
        }
        
        @Override
        public void refundPayment(Payment payment) {
            // 处理PayPal退款
        }
        
        @Override
        public void cancelPayment(Payment payment) {
            // 取消支付并退款
            refundPayment(payment);
        }
    }

    重构后:

    public interface PaymentProcessor {
        void processPayment(Payment payment);
        void refundPayment(Payment payment);
        
        default void cancelPayment(Payment payment) {
            // 默认实现:取消支付并退款
            refundPayment(payment);
        }
    }
    
    public class CreditCardProcessor implements PaymentProcessor {
        @Override
        public void processPayment(Payment payment) {
            // 处理信用卡支付
        }
        
        @Override
        public void refundPayment(Payment payment) {
            // 处理信用卡退款
        }
    }
    
    public class PayPalProcessor implements PaymentProcessor {
        @Override
        public void processPayment(Payment payment) {
            // 处理PayPal支付
        }
        
        @Override
        public void refundPayment(Payment payment) {
            // 处理PayPal退款
        }
    }

    通过使用接口默认方法,我们将公共的实现从具体的类中提取到接口中,减少了重复代码。

    当需要修改公共实现时,只需修改接口中的默认方法,而不需要修改所有实现类。

    15. 使用枚举替代常量

    使用枚举可以提供类型安全的常量,避免使用魔法数字或字符串常量。

    重构前:

    public class OrderStatus {
        public static final String PENDING = "PENDING";
        public static final String PROCESSING = "PROCESSING";
        public static final String SHIPPED = "SHIPPED";
        public static final String DELIVERED = "DELIVERED";
        public static final String CANCELLED = "CANCELLED";
    }
    
    public class Order {
        private String status;
        
        public void setStatus(String status) {
            this.status = status;
        }
        
        public String getStatus() {
            return status;
        }
        
        public boolean isCancellable() {
            return status.equals(OrderStatus.PENDING) || status.equals
            (OrderStatus.PROCESSING);
        }
    }
    
    // 使用
    Order order = new Order();
    order.setStatus(OrderStatus.PENDING);
    // 可能的错误:使用了未定义的常量
    order.setStatus("REFUNDED");

    重构后:

    public enum OrderStatus {
        PENDING,
        PROCESSING,
        SHIPPED,
        DELIVERED,
        CANCELLED;
        
        public boolean isCancellable() {
            return this == PENDING || this == PROCESSING;
        }
    }
    
    public class Order {
        private OrderStatus status;
        
        public void setStatus(OrderStatus status) {
            this.status = status;
        }
        
        public OrderStatus getStatus() {
            return status;
        }
        
        public boolean isCancellable() {
            return status.isCancellable();
        }
    }
    
    // 使用
    Order order = new Order();
    order.setStatus(OrderStatus.PENDING);
    // 编译错误:无法使用未定义的枚举常量
    // order.setStatus("REFUNDED");

    通过使用枚举,我们提供了类型安全的常量,避免了使用魔法数字或字符串常量可能导致的错误。

    同时,枚举也可以包含方法,使得与常量相关的行为更加内聚。

    总结

    在这篇文章中,我们探讨了15个代码重构的小技巧,从简单的提取方法到高级的设计模式应用。

    这些技巧可以帮助我们写出更加简洁、可读、可维护的代码。

    代码重构是一个持续的过程,我们应该在日常开发中不断地应用这些技巧,逐步改进我们的代码质量。

    AI大模型学习福利

    作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

    一、全套AGI大模型学习路线

    AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

    二、640套AI大模型报告合集

    这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

    三、AI大模型经典PDF籍

    随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。


    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

    四、AI大模型商业化落地方案

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

    作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量

    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
    红包 添加红包
    表情包 插入表情
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值