前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >重构-改善既有代码的设计之代码的坏味道举例说明

重构-改善既有代码的设计之代码的坏味道举例说明

作者头像
九转成圣
发布2024-04-10 18:37:46
发布2024-04-10 18:37:46
17600
代码可运行
举报
文章被收录于专栏:csdncsdn
运行总次数:0
代码可运行

重构-改善既有代码的设计之代码的坏味道举例说明

标签:重构-改善既有代码的设计

22种坏味道

Duplicated Code(重复代码)

Long Method(过长的方法)

Large Class(过大的类)

Long Parameter List(过长的参数列表)

Divergent Change(发散式变化)

对一个类的修改涉及到多个不相关的功能或行为时(类里有不相关的功能,违背了单一职责原则)

代码语言:javascript
代码运行次数:0
复制
public class User {
    private String username;
    private String email;
    private String password;
    private Date registrationDate;
    
    // getters and setters
    
    public void sendWelcomeEmail() {
        // 发送欢迎邮件的逻辑
    }
    public void grantPermission(String permission) {
        // 授予用户特定权限的逻辑
    }

}

解决办法提取类(Extract Class)

将不相关的功能提取到独立的类中,让每个类专注于单一的职责。在这个例子中,可以将发送邮件的逻辑提取到一个EmailSender类中,将权限管理的逻辑提取到一个UserPermissionManager类中,从而减少User类的职责,使其更符合单一职责原则。

Shotgun Surgery(散弹式修改)

描述:当需要修改一个功能时,需要在代码的多个不相关部分进行多次小的修改,而不是集中在一个地方进行修改。

假设有一个名为Order的类,用于表示系统中的订单信息。该类包含了订单的基本属性和一些与订单相关的方法。

随着系统的演化,需求变更需要在订单发生变化时记录日志。于是开发人员决定在Order类的各个方法中添加记录日志的逻辑。

代码语言:javascript
代码运行次数:0
复制
public class Order {
    private String orderId;
    private Date orderDate;
    private double totalAmount;
    
    // ...

    public void calculateTotalAmount() {
        // 计算订单总金额的逻辑
    }

    public void generateInvoice() {
        // 生成订单发票的逻辑
    }

    public void notifyCustomer() {
        // 通知顾客订单状态的逻辑
    }

    // ...
}
代码语言:javascript
代码运行次数:0
复制
public class Order {
    // ...

    public void calculateTotalAmount() {
        // 计算订单总金额的逻辑

        // 记录日志的逻辑
    }

    public void generateInvoice() {
        // 生成订单发票的逻辑

        // 记录日志的逻辑
    }

    public void notifyCustomer() {
        // 通知顾客订单状态的逻辑

        // 记录日志的逻辑
    }

    // ...
}

成为坏味道的原因:修改时容易遗漏,同时,这种修改方式也增加了代码的重复性和维护的复杂性。

解决方案:提取方法,在需要的地方调用

Feature Envy(依恋情结)

当一个方法过度依赖于另一个类的特定特性或数据,而忽略了自身所在类的特性和数据时,就存在依恋情结。

假设有一个名为Customer的类,表示系统中的顾客信息。另外还有一个名为Order的类,表示顾客的订单信息。Order类中的某个方法过度依赖于Customer类的特定特性或数据。

职责划分不清,一个应该放在Customer类中的方法放在了Order类中(放在Customer中,其他类用的时候可以调用A类,放在Order类中,其他类用的时候需要依赖Customer,重写一遍计算逻辑或者调用Order,Order类在依赖与Customer类)

代码语言:javascript
代码运行次数:0
复制
public class Order {
    private Customer customer;
    private List<String> shopList;
    // ...

    // 就算折后总金额
    public double calculateDiscountedTotal() {
        // 假设calculateDiscountedTotal方法依赖于Customer类的discount属性
        double discount = customer.getDiscount();
        // 根据折扣计算订单的折扣后总金额的逻辑
        // ...
        return discount * 商品总金额
    }

    // ...
}

在这个例子中,Order类的calculateDiscountedTotal方法过度依赖于Customer类的discount属性。这种情况违反了封装的原则,因为Order类过于了解Customer类的内部细节,导致了依恋情结。

依恋情结的一种方法是将方法移动到更适合的类中,以减少对其他类的依赖。在这个例子中,可以考虑将calculateDiscountedTotal方法移动到Customer类中,使得折扣计算的逻辑与Customer类关联。

代码语言:javascript
代码运行次数:0
复制
public class Customer {
    // ...

    public double calculateDiscountedTotal(Order order) {
        double discount = getDiscount();
        // 根据折扣计算订单的折扣后总金额的逻辑
        // ...
    }

    // ...
}

这样一来,calculateDiscountedTotal方法与Customer类关联,避免了Order类对Customer类的依恋情结。Order类不再直接依赖于Customer类的具体属性,而是通过传递Order对象给Customer类的方法来实现折扣计算。

Feature Envy(依恋情结)的问题在于方法过度依赖于另一个类的特定特性或数据,而忽略了自身所在类的特性和数据。这导致了以下问题:

  1. 违反封装原则:依恋情结违反了类的封装性,因为方法过于关注其他类的内部细节。这使得类的设计不够独立和可维护,因为它过于依赖其他类的实现细节。
  2. 高耦合性:依恋情结导致类之间的耦合度增加。当一个类过度依赖另一个类时,它们之间的关系变得紧密,修改一个类可能会影响到其他类的功能。这增加了代码的脆弱性和复杂性。
  3. 低内聚性:依恋情结导致类的内聚性降低。一个类应该关注自身的职责和功能,而不是过度关注其他类的属性和数据。当方法过于关注其他类时,类的职责不清晰,难以理解和维护。
  4. 代码重复和冗余:依恋情结可能导致代码的重复和冗余。当多个类需要使用相同的功能或数据时,如果每个类都实现一份相似的代码逻辑,就会导致代码重复。这增加了维护成本,并可能导致一致性问题。
  5. 难以扩展和修改:依恋情结使得修改和扩展变得困难。当需要修改或扩展功能时,由于方法过于依赖其他类的特性和数据,修改点会分散在多个类中,增加了修改的复杂性和风险

解决办法:将方法移到更合适的类中

Data Clumps(数据泥团)

当多个数据项经常一起出现,并且它们总是以相同的方式组合在一起使用时,就存在数据泥团.

违反了数据库的第三范式:非主属性对主属性存在传递函数依赖关系(非主属性与非主属性之间存在函数依赖关系,例如f(用户名)->用户地址)

假设有一个名为Order的类,表示系统中的订单信息。该类包含了订单的基本属性,如订单号、客户信息、商品列表等。

代码语言:javascript
代码运行次数:0
复制
public class Order {
    private String orderId;
    private String customerName;
    private String customerAddress;
    private List<String> itemList;
    
    // ...
}

在这个例子中,customerNamecustomerAddress两个属性经常一起使用,而且它们总是以相同的方式组合在一起。这种情况下,就存在数据泥团,因为这两个数据项可以组合成一个独立的类来表示客户信息,而不是分散在订单类中。

代码语言:javascript
代码运行次数:0
复制
public class Order {
    private String orderId;
    private Customer customer;
    private List<String> itemList;
    
    // ...
}

public class Customer {
    private String name;
    private String address;
    
    // ...
}

为了解决数据泥团问题,可以使用重构手法如提炼类(Extract Class)将相关的数据项提取到一个新的类中,形成一个独立的客户类。

Primitive Obsession(基本类型偏执)

过度使用基本类型(如整数、字符串)来表示领域内的概念,而不是使用更具表达力和语义的自定义类型。

代码语言:javascript
代码运行次数:0
复制
public class Product {
    private String name;
    private double price;
    private int quantity;
    
    // ...
}

如果有必要提取类的话,也就是刚开始基本类型可以实现,后来基本类型满足不了了,就没必要偏执了

代码语言:javascript
代码运行次数:0
复制
public class Product {
    private String name;
    private Money price;
    private Quantity quantity;
    
    // ...
}

public class Money {
    private double value;
    
    // ...
}

public class Quantity {
    private int value;
    
    // ...
}

解决方案:提取类

Switch Statements (switch 惊悚现身)

假设有一个名为PaymentProcessor的类,负责处理不同类型的支付方式。在该类中,根据支付方式的类型来执行相应的操作。

代码语言:javascript
代码运行次数:0
复制
public class PaymentProcessor {
    public void processPayment(Payment payment) {
        switch (payment.getType()) {
            case CREDIT_CARD:
                // 执行信用卡支付逻辑
                break;
            case PAYPAL:
                // 执行 PayPal 支付逻辑
                break;
            case BANK_TRANSFER:
                // 执行银行转账支付逻辑
                break;
            // 更多支付方式的分支
        }
    }
}
代码语言:javascript
代码运行次数:0
复制
public interface Payment {
    void processPayment();
}

public class CreditCardPayment implements Payment {
    @Override
    public void processPayment() {
        // 执行信用卡支付逻辑
    }
}

public class PaypalPayment implements Payment {
    @Override
    public void processPayment() {
        // 执行 PayPal 支付逻辑
    }
}

public class BankTransferPayment implements Payment {
    @Override
    public void processPayment() {
        // 执行银行转账支付逻辑
    }
}
代码语言:javascript
代码运行次数:0
复制
public class PaymentProcessor {
    public void processPayment(Payment payment) {
        payment.processPayment();
    }
}

解决方案:提取类

Parallel Inheritance Hierarchies(平行继承体系)

在一个系统中存在两个或多个相互关联的继承体系,这些继承体系中的类之间存在强耦合关系。以下是一个示例来说明平行继承体系的情况:

假设有一个图形编辑器的系统,其中有两个主要的继承体系:Shape(形状)和Color(颜色)。在Shape继承体系中有具体的形状类如Circle(圆形)和Rectangle(矩形),而在Color继承体系中有具体的颜色类如Red(红色)和Blue(蓝色)。这两个继承体系之间存在强耦合关系,需要相互配对使用。

代码语言:javascript
代码运行次数:0
复制
// 形状继承体系
public abstract class Shape {
    protected Color color;

    // ...
}

public class Circle extends Shape {
    // ...
}

public class Rectangle extends Shape {
    // ...
}

// 颜色继承体系
public abstract class Color {
    // ...
}

public class Red extends Color {
    // ...
}

public class Blue extends Color {
    // ...
}

在这个例子中,Shape继承体系和Color继承体系是平行的,即每个具体的形状类需要与一个具体的颜色类配对使用。例如,Circle类需要与Red类配对使用,Rectangle类需要与Blue类配对使用。这种设计使得新增或修改形状或颜色时,需要同时修改两个继承体系中的类,导致代码的脆弱性和复杂性增加。

为了解决平行继承体系的问题,可以使用桥接模式(Bridge Pattern)来分离形状和颜色的继承关系,使它们可以独立变化。桥接模式通过将一个继承体系抽象为一个独立的继承层次结构,并通过组合关系将它与另一个继承体系关联起来。

代码语言:javascript
代码运行次数:0
复制
// 形状继承体系
public abstract class Shape {
    protected Color color;

    public Shape(Color color) {
        this.color = color;
    }

    public abstract void draw();

    // ...
}

public class Circle extends Shape {
    public Circle(Color color) {
        super(color);
    }

    @Override
    public void draw() {
        // 绘制圆形
        color.fill();
    }

    // ...
}

public class Rectangle extends Shape {
    public Rectangle(Color color) {
        super(color);
    }

    @Override
    public void draw() {
        // 绘制矩形
        color.fill();
    }

    // ...
}

// 颜色继承体系
public interface Color {
    void fill();

    // ...
}

public class Red implements Color {
    @Override
    public void fill() {
        // 填充红色
    }

    // ...
}

public class Blue implements Color {
    @Override
    public void fill() {
        // 填充蓝色
    }

    // ...
}

通过桥接模式,Shape继承体系和Color继承体系被解耦,形状类和颜色类可以独立变化。每个具体的形状类通过组合关系持有一个颜色对象,并通过调用颜色对象的方法来实现绘制操作。这种设计减少了继承体系之间的耦合性,使系统更灵活、可扩展和易于维护。当新增或修改形状或颜色时,只需修改相应的类,不会对其他类造成影响。

Lazy Class (多余的类)

Speculative Generality(夸夸其谈未来性)

Temporary Field(令人迷糊的临时字段)

Message Chains(过度耦合的消息链)

在代码中存在过长的消息链式调用,即通过多个对象之间的连续方法调用来获取所需的数据或执行操作,导致代码的耦合度增加,可读性降低。以下是一个示例来说明过度耦合的消息链的情况:

假设有一个名为 Customer 的类,用于表示顾客信息。该类具有一个关联的 Order 对象,而 Order 类又关联了 Address 对象,以表示顾客的订单和地址信息。

代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Customer {
    private Order order;

    public Order getOrder() {
        return order;
    }
}

public class Order {
    private Address address;

    public Address getAddress() {
        return address;
    }
}

public class Address {
    private String street;
    private String city;
    private String country;

    public String getStreet() {
        return street;
    }

    public String getCity() {
        return city;
    }

    public String getCountry() {
        return country;
    }
}

在这个例子中,通过 Customer 对象获取顾客的国家信息可能需要经过多次连续的方法调用:

代码语言:javascript
代码运行次数:0
复制
javaCopy codeCustomer customer = new Customer();
// ...

String country = customer.getOrder().getAddress().getCountry();

这样的代码存在过度耦合的消息链,使得代码的可读性和维护性降低。如果需要修改消息链中的任何一个类或方法,都会对调用链上的多个对象产生影响。

为了解决过度耦合的消息链的问题,可以考虑以下重构方式:

  1. 引入中间对象:通过引入中间对象来封装消息链,减少直接访问链式调用的次数。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Customer {
    private Order order;

    public Order getOrder() {
        return order;
    }

    public Address getAddress() {
        return order.getAddress();
    }
}

现在,获取顾客的国家信息可以通过中间对象 Customer 的方法来获取:

代码语言:javascript
代码运行次数:0
复制
javaCopy codeCustomer customer = new Customer();
// ...

String country = customer.getAddress().getCountry();
  1. 将部分消息链提升为参数:如果只需要链中的部分数据,可以将需要的数据作为参数传递,避免直接访问整个消息链。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Customer {
    private Order order;

    public Order getOrder() {
        return order;
    }

    public String getCountry() {
        return order.getAddress().getCountry();
    }
}

现在,可以直接通过 Customer 对象获取顾客的国家信息:

代码语言:javascript
代码运行次数:0
复制
javaCopy codeCustomer customer = new Customer();
// ...

String country = customer.getCountry();

通过以上重构方式,可以减少过度耦合的消息链的使用,提高代码的可读性和维护性。避免了对多个对象的连续方法调用,使代码更加清晰和易于理解。

Middle Man(多余的中间人)

存在一些中间类或中间方法,它们仅仅是转发调用到其他类或方法,对代码逻辑没有实质性的贡献。以下是一个示例来说明中间人的情况:

假设有一个名为 Employee 的类,表示公司的员工信息。而在公司的员工管理系统中,有一个 EmployeeService 类负责处理员工相关的业务逻辑。

代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Employee {
    private String name;
    private String department;

    public String getName() {
        return name;
    }

    public String getDepartment() {
        return department;
    }
}

public class EmployeeService {
    private List<Employee> employees;

    public List<Employee> getAllEmployees() {
        // 调用中间人方法获取员工列表
        return EmployeeRepository.getAllEmployees();
    }
}

public class EmployeeRepository {
    public static List<Employee> getAllEmployees() {
        // 实际的员工数据获取逻辑

        // ...
    }
}

在这个例子中,EmployeeService 类充当了中间人的角色,它的 getAllEmployees() 方法仅仅是转发调用到 EmployeeRepository 类的 getAllEmployees() 方法,没有添加任何额外的业务逻辑。

中间人的存在可能会导致代码的冗余和复杂性增加,不利于代码的维护和扩展。对于这种情况,可以考虑以下重构方式:

  1. 直接调用被调用对象:如果中间人仅仅是转发调用到其他类的方法,可以直接在调用方调用被调用对象的方法,避免引入不必要的中间人。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class EmployeeService {
    private List<Employee> employees;

    public List<Employee> getAllEmployees() {
        // 直接调用被调用对象的方法
        return EmployeeRepository.getAllEmployees();
    }
}
  1. 移除中间人类:如果中间人类没有其他实质性的逻辑,可以直接在调用方直接调用被调用对象的方法,然后移除中间人类。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class EmployeeService {
    private List<Employee> employees;

    public List<Employee> getAllEmployees() {
        // 直接调用被调用对象的方法
        // 移除中间人类

        return EmployeeRepository.getAllEmployees();
    }
}

通过以上重构方式,可以消除不必要的中间人,简化代码结构,提高代码的可读性和可维护性。避免了仅仅转发调用的冗余代码,使代码更加清晰和易于理解。

Inappropriate Intimacy(不恰当的亲密关系|狎昵关系)

两个类之间的关系过于密切,一个类过度依赖或访问另一个类的内部细节,违反了良好的封装原则。以下是一个示例来说明狎昵关系的情况:

假设有两个类 CustomerOrder,表示顾客和订单信息。现在,Customer 类需要获取 Order 类的一些信息,但是它过度地依赖和访问了 Order 类的内部细节。

代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Customer {
    private String name;
    private Order order;

    public String getName() {
        return name;
    }

    public String getOrderStatus() {
        // 过度依赖和访问Order类的内部细节
        if (order != null && order.getStatus() != null) {
            return order.getStatus();
        }
        return "Unknown";
    }
}

public class Order {
    private String status;

    public String getStatus() {
        return status;
    }
}

在这个例子中,Customer 类需要获取 Order 类的状态信息。但是,Customer 类直接访问了 Order 类的状态属性,违反了封装的原则。这种依赖关系过于密切,当 Order 类的内部结构发生变化时,需要修改 Customer 类的代码。

为了解决狎昵关系的问题,可以考虑以下重构方式:

  1. 将操作移到正确的类中:将获取订单状态的操作移动到 Order 类中,通过提供公共的访问方法来封装内部细节。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Customer {
    private String name;
    private Order order;

    public String getName() {
        return name;
    }

    public String getOrderStatus() {
        if (order != null) {
            return order.getStatus();
        }
        return "Unknown";
    }
}

public class Order {
    private String status;

    public String getStatus() {
        return status;
    }
    
    // 其他Order类的操作和属性
}

现在,Customer 类只需要调用 Order 类的公共方法来获取订单状态,而不直接依赖和访问内部细节。

  1. 使用委托:如果 Customer 类需要更多的订单操作,可以通过委托的方式将操作交给 Order 类来处理。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Customer {
    private String name;
    private Order order;

    public String getName() {
        return name;
    }

    public String getOrderStatus() {
        if (order != null) {
            return order.getStatus();
        }
        return "Unknown";
    }
    
    public void cancelOrder() {
        if (order != null) {
            order.cancel();
        }
    }
}

public class Order {
    private String status;

    public String getStatus() {
        return status;
    }
    
    public void cancel() {
        // 取消订单的操作
    }
    
    // 其他Order类的操作和属性
}

通过委托的方式,Customer 类将订单操作委托给 Order 类进行处理,减少了类之间的耦合性,提高了代码的可维护性和灵活性。

通过以上重构方式,可以解决狎昵关系带来的问题,减少类之间的依赖,增强代码的封装性和可扩展性。

Alternative Classes with Different Interfaces(异曲同工的类)

存在两个或多个类,它们实现了相似的功能,但使用了不同的接口或方法命名,导致代码的可读性和维护性降低。以下是一个示例来说明异曲同工的类的情况:

假设有两个类 RectangleSquare,表示矩形和正方形。它们都有计算面积和周长的方法,但使用了不同的接口或方法命名。

代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class Rectangle {
    private int width;
    private int height;

    public int calculateArea() {
        return width * height;
    }

    public int calculatePerimeter() {
        return 2 * (width + height);
    }
}

public class Square {
    private int sideLength;

    public int calculateSquareArea() {
        return sideLength * sideLength;
    }

    public int calculateSquarePerimeter() {
        return 4 * sideLength;
    }
}

在这个例子中,Rectangle 类和 Square 类都表示不同的几何形状,但是它们的功能是相似的:计算面积和周长。然而,它们使用了不同的方法命名和接口,使得代码阅读和维护变得困难。

为了解决异曲同工的类的问题,可以考虑以下重构方式:

  1. 统一接口和方法命名:将类的接口和方法命名统一,使得功能相似的类使用相同的接口和方法。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic interface Shape {
    int calculateArea();

    int calculatePerimeter();
}

public class Rectangle implements Shape {
    private int width;
    private int height;

    @Override
    public int calculateArea() {
        return width * height;
    }

    @Override
    public int calculatePerimeter() {
        return 2 * (width + height);
    }
}

public class Square implements Shape {
    private int sideLength;

    @Override
    public int calculateArea() {
        return sideLength * sideLength;
    }

    @Override
    public int calculatePerimeter() {
        return 4 * sideLength;
    }
}

通过定义一个统一的接口 Shape,将功能相似的类统一到同一个接口下,并使用相同的方法命名,提高了代码的可读性和维护性。

  1. 继承关系:如果存在一些共同的属性和方法,可以考虑使用继承来消除重复代码。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic abstract class Shape {
    // 公共属性和方法

    public abstract int calculateArea();

    public abstract int calculatePerimeter();
}

public class Rectangle extends Shape {
    private int width;
    private int height;

    @Override
    public int calculateArea() {
        return width * height;
    }

    @Override
    public int calculatePerimeter() {
        return 2 * (width + height);
    }
}

public class Square extends Shape {
    private int sideLength;

    @Override
    public int calculateArea()

Incomplete Library Class(不完整的库类)

库或框架中的某个类功能不完整,缺少某些常用的方法或功能,导致开发者需要自行补充或扩展该类的功能。以下是一个示例来说明不完整的库类的情况:

假设我们使用一个第三方库中的 StringUtils 类来处理字符串相关操作。然而,该类缺少一些常用的方法,比如截取子串、替换字符串等。

代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class StringUtils {
    // 该类缺少一些常用的方法

    public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }

    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }
}

在这个例子中,StringUtils 类是一个常用的字符串处理类,但是它缺少一些常用的方法,限制了开发者在处理字符串时的灵活性。为了补充缺失的功能,开发者可能需要自行编写或扩展该类的功能,增加了额外的工作量和复杂度。

为了解决不完整的库类的问题,可以考虑以下重构方式:

  1. 扩展库类:创建一个新的类,继承库类并添加缺失的方法或功能。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class EnhancedStringUtils extends StringUtils {
    public static String substring(String str, int startIndex, int endIndex) {
        // 添加截取子串的功能
        if (str == null || startIndex < 0 || endIndex < 0 || startIndex >= str.length() || endIndex > str.length()) {
            throw new IllegalArgumentException("Invalid arguments");
        }
        return str.substring(startIndex, endIndex);
    }

    public static String replace(String str, String oldSubstring, String newSubstring) {
        // 添加替换字符串的功能
        if (str == null || oldSubstring == null || newSubstring == null) {
            throw new IllegalArgumentException("Invalid arguments");
        }
        return str.replace(oldSubstring, newSubstring);
    }
}

通过创建一个新的类 EnhancedStringUtils,继承原始的 StringUtils 类并添加缺失的方法或功能,可以补充库类的不完整功能,提供更全面的字符串处理功能。

  1. 自定义工具类:如果需要的功能较多或更复杂,可以考虑创建一个自定义的工具类,提供完整的功能集合。
代码语言:javascript
代码运行次数:0
复制
javaCopy codepublic class CustomStringUtils {
    public static String substring(String str, int startIndex, int endIndex) {
        // 添加截取子串的功能
        if (str == null || startIndex < 0 || endIndex < 0 || startIndex >= str.length() || endIndex > str.length()) {
            throw new IllegalArgumentException("Invalid arguments");
        }
        return str.substring(startIndex, endIndex);
    }

    public static String replace(String str, String oldSubstring, String newSubstring) {
        // 添加替换字符串的功能
        if (str == null || oldSubstring == null || newSubstring == null) {
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 重构-改善既有代码的设计之代码的坏味道举例说明
    • 标签:重构-改善既有代码的设计
  • Duplicated Code(重复代码)
  • Long Method(过长的方法)
  • Large Class(过大的类)
  • Long Parameter List(过长的参数列表)
  • Divergent Change(发散式变化)
  • Shotgun Surgery(散弹式修改)
  • Feature Envy(依恋情结)
  • Data Clumps(数据泥团)
  • Primitive Obsession(基本类型偏执)
  • Switch Statements (switch 惊悚现身)
  • Parallel Inheritance Hierarchies(平行继承体系)
  • Lazy Class (多余的类)
  • Speculative Generality(夸夸其谈未来性)
  • Temporary Field(令人迷糊的临时字段)
  • Message Chains(过度耦合的消息链)
  • Middle Man(多余的中间人)
  • Inappropriate Intimacy(不恰当的亲密关系|狎昵关系)
  • Alternative Classes with Different Interfaces(异曲同工的类)
  • Incomplete Library Class(不完整的库类)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档