首页 > 编程语言 >Java代码优化中的六大原则

Java代码优化中的六大原则

时间:2024-10-15 15:46:04浏览次数:10  
标签:六大 Java String double void private public 代码优化 order

目录

一.单一职责原则 (Single Responsibility Principle, SRP)

1. 定义

2. 核心思想

3. 好处

4. 实践案例

案例:日志记录与业务逻辑分离

5. 总结

二.DRY原则 (Don't Repeat Yourself)

1. 定义

2. 核心思想

3. 好处

4. 实践案例

案例1:提取公共方法

案例2:使用模板方法模式

5. 总结

三.开闭原则 (Open/Closed Principle, OCP)

1. 定义

2. 核心思想

3. 好处

4. 实践案例

案例:策略模式

5. 总结

四.里氏替换原则 (Liskov Substitution Principle, LSP)

1. 定义

2. 核心思想

3. 好处

4. 实践案例

案例:正方形和矩形问题

5. 总结

五.接口隔离原则 (Interface Segregation Principle, ISP)

1. 定义

2. 核心思想

3. 好处

4. 实践案例

案例1:打印机接口

案例2:支付系统接口

5. 总结

六.迪米特原则 (Law of Demeter, LoD)

1. 定义

2. 核心思想

3. 好处

4. 实践案例

案例1:用户和订单系统

案例2:车辆和引擎系统

5. 总结

七.总结


一.单一职责原则 (Single Responsibility Principle, SRP)

1. 定义

单一职责原则(SRP)是面向对象设计的SOLID原则之一,由Robert C. Martin在2000年提出。该原则指出,一个类应该只有一个引起它变化的原因,也就是说,一个类应该只负责一项功能或职责。

2. 核心思想
  • 单一职责:每个类应该专注于完成一个特定的功能。
  • 高内聚:类内的方法应该紧密相关,共同服务于同一个目的。
  • 低耦合:类与类之间应该尽量减少依赖关系,保持松散耦合。
3. 好处
  • 可维护性:当类的职责单一时,修改一个功能不会影响到其他功能,从而降低维护成本。
  • 可测试性:单一职责的类更容易进行单元测试,因为它们的功能明确且独立。
  • 可读性:类的职责清晰,使得代码更加易于理解和阅读。
  • 可扩展性:随着需求的变化,单一职责的类更容易扩展和重构。
4. 实践案例
案例:日志记录与业务逻辑分离

假设有一个处理用户注册的类 UserRegistrationService,其中包含日志记录和业务逻辑:

public class UserRegistrationService {
    public void registerUser(User user) {
        // 日志记录
        System.out.println("Registering user: " + user.getName());

        // 业务逻辑
        if (user.isValid()) {
            saveUserToDatabase(user);
            sendWelcomeEmail(user);
        } else {
            throw new IllegalArgumentException("Invalid user data");
        }
    }

    private void saveUserToDatabase(User user) {
        // 保存用户到数据库
    }

    private void sendWelcomeEmail(User user) {
        // 发送欢迎邮件
    }
}

根据SRP,我们可以将日志记录的责任从 UserRegistrationService 中分离出来,使用日志框架(如SLF4J)来处理日志记录:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserRegistrationService {
    private static final Logger logger = LoggerFactory.getLogger(UserRegistrationService.class);

    public void registerUser(User user) {
        // 业务逻辑
        if (user.isValid()) {
            saveUserToDatabase(user);
            sendWelcomeEmail(user);
        } else {
            throw new IllegalArgumentException("Invalid user data");
        }
    }

    private void saveUserToDatabase(User user) {
        // 保存用户到数据库
        logger.info("Saving user to database: {}", user.getName());
    }

    private void sendWelcomeEmail(User user) {
        // 发送欢迎邮件
        logger.info("Sending welcome email to: {}", user.getEmail());
    }
}

在这个例子中,日志记录的责任被转移到了日志框架,而 UserRegistrationService 只关注于用户注册的业务逻辑。

5. 总结

单一职责原则是编写高质量、可维护代码的重要指导原则。通过确保每个类只负责一项功能,可以提高代码的可读性、可测试性和可维护性。在实际开发中,应始终遵循这一原则,并通过不断重构来保持代码的简洁和清晰。

二.DRY原则 (Don't Repeat Yourself)

1. 定义

DRY(Don't Repeat Yourself)原则是软件开发中的一项基本原则,强调在系统中每个知识或逻辑表达应该有一个单一、明确的表示。换句话说,避免在多个地方重复相同的代码逻辑。

2. 核心思想
  • 避免冗余:减少代码中的重复部分,确保每个功能只在一个地方实现。
  • 提高可维护性:一处修改,处处生效。当需要更改某个功能时,只需在一个地方进行修改,而不需要在多个地方同时修改。
  • 增强一致性:通过集中管理逻辑,确保行为的一致性和正确性。
3. 好处
  • 可维护性:简化代码维护工作,降低出错概率。
  • 可读性:代码更加简洁和清晰,易于理解和阅读。
  • 可扩展性:更容易添加新功能或修改现有功能。
  • 减少错误:减少因复制粘贴导致的错误。
4. 实践案例
案例1:提取公共方法

假设你有一个处理用户输入的类 UserInputProcessor,其中有两个方法分别处理不同类型的输入:

public class UserInputProcessor {
    public void processEmail(String email) {
        if (email == null || email.isEmpty()) {
            throw new IllegalArgumentException("Email cannot be empty");
        }
        // 处理电子邮件逻辑
    }

    public void processPhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.isEmpty()) {
            throw new IllegalArgumentException("Phone number cannot be empty");
        }
        // 处理电话号码逻辑
    }
}

这里,对输入为空的检查逻辑是重复的。我们可以提取一个公共方法来处理这种验证:

public class UserInputProcessor {
    private void validateNotEmpty(String input, String fieldName) {
        if (input == null || input.isEmpty()) {
            throw new IllegalArgumentException(fieldName + " cannot be empty");
        }
    }

    public void processEmail(String email) {
        validateNotEmpty(email, "Email");
        // 处理电子邮件逻辑
    }

    public void processPhoneNumber(String phoneNumber) {
        validateNotEmpty(phoneNumber, "Phone number");
        // 处理电话号码逻辑
    }
}
案例2:使用模板方法模式

假设你有一个处理订单的类 OrderProcessor,其中有多种类型的订单处理逻辑,但它们都有一些共同的步骤:

public class OrderProcessor {
    public void processStandardOrder(Order order) {
        logStart(order);
        validateOrder(order);
        calculateTotal(order);
        applyDiscount(order);
        saveOrder(order);
        logEnd(order);
    }

    public void processBulkOrder(Order order) {
        logStart(order);
        validateOrder(order);
        calculateTotal(order);
        applyBulkDiscount(order);
        saveOrder(order);
        logEnd(order);
    }

    private void logStart(Order order) {
        System.out.println("Processing order: " + order.getId());
    }

    private void logEnd(Order order) {
        System.out.println("Finished processing order: " + order.getId());
    }

    private void validateOrder(Order order) {
        // 验证订单逻辑
    }

    private void calculateTotal(Order order) {
        // 计算总价逻辑
    }

    private void applyDiscount(Order order) {
        // 应用折扣逻辑
    }

    private void applyBulkDiscount(Order order) {
        // 应用批量折扣逻辑
    }

    private void saveOrder(Order order) {
        // 保存订单逻辑
    }
}

这里,processStandardOrderprocessBulkOrder 方法有很多重复的步骤。我们可以使用模板方法模式来避免这些重复:

public abstract class OrderProcessor {
    public final void processOrder(Order order) {
        logStart(order);
        validateOrder(order);
        calculateTotal(order);
        applySpecificDiscount(order);
        saveOrder(order);
        logEnd(order);
    }

    protected abstract void applySpecificDiscount(Order order);

    private void logStart(Order order) {
        System.out.println("Processing order: " + order.getId());
    }

    private void logEnd(Order order) {
        System.out.println("Finished processing order: " + order.getId());
    }

    private void validateOrder(Order order) {
        // 验证订单逻辑
    }

    private void calculateTotal(Order order) {
        // 计算总价逻辑
    }

    private void saveOrder(Order order) {
        // 保存订单逻辑
    }
}

public class StandardOrderProcessor extends OrderProcessor {
    @Override
    protected void applySpecificDiscount(Order order) {
        applyDiscount(order);
    }

    private void applyDiscount(Order order) {
        // 应用折扣逻辑
    }
}

public class BulkOrderProcessor extends OrderProcessor {
    @Override
    protected void applySpecificDiscount(Order order) {
        applyBulkDiscount(order);
    }

    private void applyBulkDiscount(Order order) {
        // 应用批量折扣逻辑
    }
}

在这个例子中,OrderProcessor 类定义了一个模板方法 processOrder,并将具体的折扣应用逻辑委托给子类实现。这样可以避免重复代码,并且使逻辑更加清晰和灵活。

5. 总结

DRY原则是编写高质量代码的重要指导原则。通过避免代码重复,可以提高代码的可维护性、可读性和一致性。在实际开发中,应始终遵循这一原则,并通过重构来消除冗余代码。常见的实践包括提取公共方法、使用模板方法模式以及合理利用继承和组合等设计模式。

三.开闭原则 (Open/Closed Principle, OCP)

1. 定义

开闭原则(Open/Closed Principle, OCP)是面向对象设计的SOLID原则之一,由Bertrand Meyer在1988年提出。该原则指出,软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。也就是说,一个软件实体应该能够在不修改其源代码的情况下进行扩展。

2. 核心思想
  • 对扩展开放:允许通过添加新的代码来扩展系统的行为。
  • 对修改关闭:现有代码不应该被修改,以避免引入新的错误或破坏现有的功能。
3. 好处
  • 可维护性:减少因修改现有代码而导致的风险,提高系统的稳定性。
  • 可扩展性:通过添加新代码而不是修改现有代码来实现新功能,使系统更加灵活。
  • 降低耦合:通过接口和抽象类来定义行为,减少了具体实现之间的依赖。
4. 实践案例
案例:策略模式

假设你有一个支付系统,支持多种支付方式(如信用卡支付、PayPal支付等)。初始实现可能如下:

public class PaymentProcessor {
    public void processPayment(Payment payment) {
        if (payment.getMethod().equals("credit_card")) {
            // 信用卡支付逻辑
        } else if (payment.getMethod().equals("paypal")) {
            // PayPal支付逻辑
        }
    }
}

这种实现方式违反了开闭原则,因为每增加一种新的支付方式都需要修改 processPayment 方法。我们可以使用策略模式来改进这个设计:

// 支付策略接口
public interface PaymentStrategy {
    void pay(double amount);
}

// 信用卡支付策略
public class CreditCardPaymentStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        // 信用卡支付逻辑
    }
}

// PayPal支付策略
public class PayPalPaymentStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        // PayPal支付逻辑
    }
}

// 支付处理器
public class PaymentProcessor {
    private final PaymentStrategy strategy;

    public PaymentProcessor(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void processPayment(double amount) {
        strategy.pay(amount);
    }
}

在这个例子中,PaymentProcessor 类通过依赖注入的方式接受一个 PaymentStrategy 接口的实现。当需要添加新的支付方式时,只需创建一个新的 PaymentStrategy 实现类,而不需要修改现有的 PaymentProcessor 类。

5. 总结

开闭原则是编写高质量、可维护代码的重要指导原则。通过确保系统对扩展开放而对修改关闭,可以提高代码的灵活性和稳定性。常见的实践包括使用策略模式、工厂模式、装饰器模式等设计模式,以及合理利用接口和抽象类来定义行为。遵循开闭原则可以帮助开发者构建更加健壮和易于扩展的系统。

四.里氏替换原则 (Liskov Substitution Principle, LSP)

1. 定义

里氏替换原则(Liskov Substitution Principle, LSP)是面向对象设计的SOLID原则之一,由Barbara Liskov在1987年提出。该原则指出,子类对象应该能够替换其父类对象而不影响程序的正确性。换句话说,如果一个程序依赖于基类,那么它应该能够在不知道具体子类的情况下使用这些子类的对象。

2. 核心思想
  • 行为一致性:子类必须完全实现父类的行为,并且不能改变父类的方法签名。
  • 前置条件:子类可以放宽父类方法的前置条件,但不能加强它们。
  • 后置条件:子类可以加强父类方法的后置条件,但不能放宽它们。
  • 不变量:子类必须保持父类的所有不变量。
3. 好处
  • 可扩展性:允许通过继承来扩展功能,而不会破坏现有代码。
  • 可维护性:确保子类与父类之间的兼容性,减少因修改子类而导致的问题。
  • 灵活性:使系统更加灵活,可以在运行时动态地选择具体的子类实现。
4. 实践案例
案例:正方形和矩形问题

假设我们有一个 Rectangle 类,其中包含宽度和高度属性:

public class Rectangle {
    private double width;
    private double height;

    public void setWidth(double width) {
        this.width = width;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWidth() {
        return width;
    }

    public double getHeight() {
        return height;
    }
}

如果我们试图创建一个 Square 类来继承 Rectangle,并强制宽度和高度相等:

public class Square extends Rectangle {
    @Override
    public void setWidth(double width) {
        super.setWidth(width);
        super.setHeight(width); // 强制宽度和高度相等
    }

    @Override
    public void setHeight(double height) {
        super.setHeight(height);
        super.setWidth(height); // 强制宽度和高度相等
    }
}

这种实现方式违反了里氏替换原则,因为如果在某个地方使用 Rectangle 的代码中替换成 Square,可能会导致意外的结果。例如,以下代码会出错:

public static void main(String[] args) {
    Rectangle rectangle = new Rectangle();
    rectangle.setWidth(5);
    rectangle.setHeight(10);

    System.out.println("Area: " + rectangle.getWidth() * rectangle.getHeight()); // 输出 50

    Rectangle square = new Square();
    square.setWidth(5);
    square.setHeight(10); // 这里实际上会设置宽度和高度都为10

    System.out.println("Area: " + square.getWidth() * square.getHeight()); // 输出 100
}

为了遵守里氏替换原则,我们可以重新设计类结构,避免直接继承 Rectangle,而是使用组合或接口来表示形状:

// 形状接口
public interface Shape {
    double getArea();
}

// 矩形类
public class Rectangle implements Shape {
    private double width;
    private double height;

    public void setWidth(double width) {
        this.width = width;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public double getArea() {
        return width * height;
    }
}

// 正方形类
public class Square implements Shape {
    private double side;

    public void setSide(double side) {
        this.side = side;
    }

    @Override
    public double getArea() {
        return side * side;
    }
}

// 使用示例
public static void main(String[] args) {
    Shape rectangle = new Rectangle();
    ((Rectangle) rectangle).setWidth(5);
    ((Rectangle) rectangle).setHeight(10);

    System.out.println("Area: " + rectangle.getArea()); // 输出 50

    Shape square = new Square();
    ((Square) square).setSide(5);

    System.out.println("Area: " + square.getArea()); // 输出 25
}

在这个例子中,RectangleSquare 都实现了 Shape 接口,这样就避免了直接继承带来的问题,并且符合里氏替换原则。

5. 总结

里氏替换原则是编写高质量、可维护代码的重要指导原则。通过确保子类可以替换其父类而不影响程序的正确性,可以提高代码的灵活性和稳定性。常见的实践包括合理设计类层次结构、使用接口和抽象类来定义行为、避免违反前置条件和后置条件。遵循里氏替换原则可以帮助开发者构建更加健壮和易于扩展的系统。

五.接口隔离原则 (Interface Segregation Principle, ISP)

1. 定义

接口隔离原则(Interface Segregation Principle, ISP)是面向对象设计的SOLID原则之一,由Robert C. Martin提出。该原则指出,客户端不应该被迫依赖于它们不使用的接口。换句话说,一个类应该只实现它实际需要的方法,而不是实现一个大而全的接口。

2. 核心思想
  • 细粒度接口:将大而全的接口拆分为多个小的、特定功能的接口。
  • 按需实现:客户端类只需要实现它们真正需要的方法,避免不必要的方法暴露。
  • 高内聚:每个接口应该具有高度内聚性,即接口中的方法应该是紧密相关的。
3. 好处
  • 可维护性:减少类之间的耦合,提高系统的可维护性。
  • 可扩展性:更容易添加新的功能,而不会影响现有的实现。
  • 清晰性:接口更加清晰和专注,易于理解和使用。
4. 实践案例
案例1:打印机接口

假设我们有一个 Printer 接口,其中包含多种打印方法:

public interface Printer {
    void printDocument(String document);
    void scanDocument(String document);
    void faxDocument(String document);
}

现在有两个具体的实现类:BasicPrinterAdvancedPrinterBasicPrinter 只支持打印功能,而 AdvancedPrinter 支持打印、扫描和传真功能。

public class BasicPrinter implements Printer {
    @Override
    public void printDocument(String document) {
        System.out.println("Printing document: " + document);
    }

    @Override
    public void scanDocument(String document) {
        throw new UnsupportedOperationException("Basic printer does not support scanning");
    }

    @Override
    public void faxDocument(String document) {
        throw new UnsupportedOperationException("Basic printer does not support faxing");
    }
}

public class AdvancedPrinter implements Printer {
    @Override
    public void printDocument(String document) {
        System.out.println("Printing document: " + document);
    }

    @Override
    public void scanDocument(String document) {
        System.out.println("Scanning document: " + document);
    }

    @Override
    public void faxDocument(String document) {
        System.out.println("Faxing document: " + document);
    }
}

这种实现方式违反了接口隔离原则,因为 BasicPrinter 被迫实现了它不需要的方法。我们可以将 Printer 接口拆分为多个更小的接口

// 打印接口
public interface Printable {
    void printDocument(String document);
}

// 扫描接口
public interface Scannable {
    void scanDocument(String document);
}

// 传真接口
public interface Faxable {
    void faxDocument(String document);
}

然后,根据具体需求让实现类实现相应的接口:

public class BasicPrinter implements Printable {
    @Override
    public void printDocument(String document) {
        System.out.println("Printing document: " + document);
    }
}

public class AdvancedPrinter implements Printable, Scannable, Faxable {
    @Override
    public void printDocument(String document) {
        System.out.println("Printing document: " + document);
    }

    @Override
    public void scanDocument(String document) {
        System.out.println("Scanning document: " + document);
    }

    @Override
    public void faxDocument(String document) {
        System.out.println("Faxing document: " + document);
    }
}

在这个例子中,BasicPrinter 只实现了 Printable 接口,而 AdvancedPrinter 实现了 Printable, Scannable, 和 Faxable 接口。这样就符合了接口隔离原则,每个类只需要实现它实际需要的方法。

案例2:支付系统接口

假设我们有一个支付系统,支持多种支付方式(如信用卡支付、PayPal支付等)。初始实现可能如下:

public interface PaymentProcessor {
    void processCreditCardPayment(double amount);
    void processPayPalPayment(double amount);
    void processBankTransferPayment(double amount);
}

现在有两个具体的实现类:CreditCardPaymentProcessorPayPalPaymentProcessorCreditCardPaymentProcessor 只支持信用卡支付,而 PayPalPaymentProcessor 只支持PayPal支付。

public class CreditCardPaymentProcessor implements PaymentProcessor {
    @Override
    public void processCreditCardPayment(double amount) {
        System.out.println("Processing credit card payment: " + amount);
    }

    @Override
    public void processPayPalPayment(double amount) {
        throw new UnsupportedOperationException("Credit card processor does not support PayPal payments");
    }

    @Override
    public void processBankTransferPayment(double amount) {
        throw new UnsupportedOperationException("Credit card processor does not support bank transfer payments");
    }
}

public class PayPalPaymentProcessor implements PaymentProcessor {
    @Override
    public void processCreditCardPayment(double amount) {
        throw new UnsupportedOperationException("PayPal processor does not support credit card payments");
    }

    @Override
    public void processPayPalPayment(double amount) {
        System.out.println("Processing PayPal payment: " + amount);
    }

    @Override
    public void processBankTransferPayment(double amount) {
        throw new UnsupportedOperationException("PayPal processor does not support bank transfer payments");
    }
}

这种实现方式违反了接口隔离原则,因为每个处理器都被迫实现了它不需要的方法。我们可以将 PaymentProcessor 接口拆分为多个更小的接口:

// 信用卡支付接口
public interface CreditCardPaymentProcessor {
    void processCreditCardPayment(double amount);
}

// PayPal支付接口
public interface PayPalPaymentProcessor {
    void processPayPalPayment(double amount);
}

// 银行转账支付接口
public interface BankTransferPaymentProcessor {
    void processBankTransferPayment(double amount);
}

然后,根据具体需求让实现类实现相应的接口:

public class CreditCardPaymentProcessorImpl implements CreditCardPaymentProcessor {
    @Override
    public void processCreditCardPayment(double amount) {
        System.out.println("Processing credit card payment: " + amount);
    }
}

public class PayPalPaymentProcessorImpl implements PayPalPaymentProcessor {
    @Override
    public void processPayPalPayment(double amount) {
        System.out.println("Processing PayPal payment: " + amount);
    }
}

public class BankTransferPaymentProcessorImpl implements BankTransferPaymentProcessor {
    @Override
    public void processBankTransferPayment(double amount) {
        System.out.println("Processing bank transfer payment: " + amount);
    }
}

在这个例子中,每个处理器只实现了它实际需要的方法,从而符合了接口隔离原则。

5. 总结

接口隔离原则是编写高质量、可维护代码的重要指导原则。通过确保客户端只依赖于它们实际需要的接口,可以减少类之间的耦合,提高系统的可维护性和可扩展性。常见的实践包括将大而全的接口拆分为多个小的、特定功能的接口,并且让实现类按需实现这些接口。遵循接口隔离原则可以帮助开发者构建更加健壮和灵活的系统。

六.迪米特原则 (Law of Demeter, LoD)

1. 定义

迪米特原则(Law of Demeter, LoD),也称为最少知识原则(Principle of Least Knowledge, POLK),是面向对象设计的一个重要原则。该原则指出,一个对象应该对其他对象有最少的了解。具体来说,一个对象应当只与直接的朋友(如成员变量、方法参数、方法返回值等)通信,而不要和陌生的对象进行交互。

2. 核心思想
  • 最小化依赖:减少类之间的直接依赖关系。
  • 封装性:通过封装来隐藏内部实现细节,只暴露必要的接口。
  • 高内聚低耦合:提高类的内聚性,降低类之间的耦合度。
3. 好处
  • 可维护性:减少类之间的耦合,使代码更易于维护。
  • 可扩展性:更容易添加新的功能或修改现有功能,而不影响其他部分。
  • 清晰性:代码更加清晰,职责更加明确。
4. 实践案例
案例1:用户和订单系统

假设我们有一个用户和订单系统,其中 User 类包含 Order 对象。初始实现可能如下:

public class User {
    private String name;
    private Order order;

    public User(String name, Order order) {
        this.name = name;
        this.order = order;
    }

    public String getName() {
        return name;
    }

    public Order getOrder() {
        return order;
    }
}

public class Order {
    private String product;
    private double price;

    public Order(String product, double price) {
        this.product = product;
        this.price = price;
    }

    public String getProduct() {
        return product;
    }

    public double getPrice() {
        return price;
    }
}

public class OrderProcessor {
    public void process(User user) {
        // 直接访问 User 的 Order 对象
        Order order = user.getOrder();
        String product = order.getProduct();
        double price = order.getPrice();

        System.out.println("Processing order for " + user.getName());
        System.out.println("Product: " + product);
        System.out.println("Price: " + price);
    }
}

这种实现方式违反了迪米特原则,因为 OrderProcessor 直接访问了 User 对象的 Order 对象,并进一步访问了 Order 的属性。我们可以改进这个设计,让 User 类提供必要的方法来获取相关信息:

public class User {
    private String name;
    private Order order;

    public User(String name, Order order) {
        this.name = name;
        this.order = order;
    }

    public String getName() {
        return name;
    }

    public String getProductName() {
        return order.getProduct();
    }

    public double getProductPrice() {
        return order.getPrice();
    }
}

public class OrderProcessor {
    public void process(User user) {
        // 通过 User 类的方法获取信息
        String productName = user.getProductName();
        double productPrice = user.getProductPrice();

        System.out.println("Processing order for " + user.getName());
        System.out.println("Product: " + productName);
        System.out.println("Price: " + productPrice);
    }
}

在这个例子中,OrderProcessor 只与 User 对象通信,不再直接访问 Order 对象,从而符合迪米特原则。

案例2:车辆和引擎系统

假设我们有一个车辆和引擎系统,其中 Vehicle 类包含 Engine 对象。初始实现可能如下:

public class Engine {
    private int horsepower;

    public Engine(int horsepower) {
        this.horsepower = horsepower;
    }

    public int getHorsepower() {
        return horsepower;
    }
}

public class Vehicle {
    private String model;
    private Engine engine;

    public Vehicle(String model, Engine engine) {
        this.model = model;
        this.engine = engine;
    }

    public String getModel() {
        return model;
    }

    public Engine getEngine() {
        return engine;
    }
}

public class VehicleInfoPrinter {
    public void print(Vehicle vehicle) {
        // 直接访问 Vehicle 的 Engine 对象
        Engine engine = vehicle.getEngine();
        int horsepower = engine.getHorsepower();

        System.out.println("Model: " + vehicle.getModel());
        System.out.println("Horsepower: " + horsepower);
    }
}

这种实现方式违反了迪米特原则,因为 VehicleInfoPrinter 直接访问了 Vehicle 对象的 Engine 对象,并进一步访问了 Engine 的属性。我们可以改进这个设计,让 Vehicle 类提供必要的方法来获取相关信息:

public class Vehicle {
    private String model;
    private Engine engine;

    public Vehicle(String model, Engine engine) {
        this.model = model;
        this.engine = engine;
    }

    public String getModel() {
        return model;
    }

    public int getEngineHorsepower() {
        return engine.getHorsepower();
    }
}

public class VehicleInfoPrinter {
    public void print(Vehicle vehicle) {
        // 通过 Vehicle 类的方法获取信息
        String model = vehicle.getModel();
        int horsepower = vehicle.getEngineHorsepower();

        System.out.println("Model: " + model);
        System.out.println("Horsepower: " + horsepower);
    }
}

在这个例子中,VehicleInfoPrinter 只与 Vehicle 对象通信,不再直接访问 Engine 对象,从而符合迪米特原则。

5. 总结

迪米特原则是编写高质量、可维护代码的重要指导原则。通过确保一个对象只与直接的朋友通信,可以减少类之间的耦合,提高系统的可维护性和可扩展性。常见的实践包括:

  • 封装内部实现细节,只暴露必要的接口。
  • 提供中介方法来访问子对象的信息。
  • 使用数据传输对象(DTO)来传递复杂的数据结构。

七.总结

这六大原则是面向对象设计中的SOLID原则加上DRY原则,它们共同构成了编写高质量Java代码的基础。通过遵循这些原则,开发者可以构建出更加健壮、灵活和易于维护的系统。具体来说:

  • 单一职责原则 和 接口隔离原则 强调了类和接口的专注性,使得每个组件都有明确的责任。
  • 开闭原则 和 里氏替换原则 关注的是继承和扩展的正确使用,确保系统在扩展时不会破坏现有的行为。
  • 迪米特原则 通过减少对象间的直接依赖,提高了系统的松耦合性。
  • DRY原则 则强调了代码复用的重要性,避免重复代码带来的维护问题。

标签:六大,Java,String,double,void,private,public,代码优化,order
From: https://blog.csdn.net/2401_85648342/article/details/142953072

相关文章

  • Java 列表元素自定义排序
    在Java开发过程中,有时会遇到需要对列表中元素进行自定义的排序。这样的排序往往不能由元素本身的特性(比如字符串长度、首字母顺序)判断,需要自己指定顺序。比如对汉字的数字进行排序,他们的字符串长度都为1,首字母顺序也不能得到预期的结果,因此需要自定义排序。以下是示例代码:p......
  • Java变量类型
    在Java中,变量根据声明位置、数据类型、是否有初始值等属性,可以分为多种类型。具体来说,Java中的变量类型可以分为以下几类:1.按数据类型分类1.1.基本数据类型(PrimitiveTypes)Java提供了8种基本数据类型,用于存储简单的数据。它们包括:整数类型:byte:8位,取值范围-128......
  • Java字段初始化规律
    publicclassmm{publicstaticvoidmain(String[]args){InitializeBlockClassobj=newInitializeBlockClass();System.out.println(obj.field);obj=newInitializeBlockClass(300);System.out.println(obj.field);}}classInitializeBlockClas......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript购物商城
    HTML+CSS+JS【购物商场】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • 2024年最新版Java面试八股文!
    1、并发编程三要素?(1)原子性原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行。(2)可见性可见性指多个线程操作一个共享变量时,其中一个线程对变量进行修改后,其他线程可以立即看到修改的结果。(3)有序性有序性,即程序的执行......
  • java+vue计算机毕设高校消防设施管理系统【源码+程序+论文+开题】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、选题背景关于高校消防设施管理的研究,现有研究多侧重于消防安全管理的一般性原则和措施,主要以整体建筑或公共场所消防管理为主。专门针对高校这一特殊环境......
  • java+vue计算机毕设高校校园一卡通管理系统【源码+程序+论文+开题】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、选题背景关于高校校园一卡通管理系统的研究,现有研究多侧重于其技术实现和功能拓展方面,如硬件设施的升级或特定功能模块(如消费功能)的优化等11。专门针对整......
  • java+vue计算机毕设高校教材征订管理系统【源码+程序+论文+开题】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、选题背景关于高校教材征订管理系统的研究,现有研究多侧重于教学管理系统整体框架的构建,对于教材征订这一特定环节的专门研究较少。在国内外高校管理领域,虽......
  • java+vue计算机毕设高校人事管理系统【源码+程序+论文+开题】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、选题背景关于高校人事管理系统的研究,现有研究主要以通用的人事管理功能为主,专门针对高校特定人事管理流程如职称评审、任期考核等的研究较少。在国内外,人......
  • java毕业设计-基于springboot+vue的阳光馨园小区废品收购管理系统设计和实现,基于sprin
    博主介绍:✌️码农一枚,专注于大学生项目实战开发、讲解和毕业......