面向对象的五大原则
- 单一职责原则(Single Responsibility Principle, SRP):
- 一个类应该仅有一个引起它变化的原因。换句话说,一个类应该只负责一项职责。
- 目的是使类保持内聚,并降低类的复杂度,从而使其更易于理解和维护。
- 开放封闭原则(Open-Closed Principle, OCP):
- 软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。
- 意思是软件应该能够通过扩展来适应变化,而不是通过修改现有代码来实现。这有助于减少代码的维护成本和引入新错误的风险。
- 里氏替换原则(Liskov Substitution Principle, LSP):
- 子类型必须能够替换掉它们的基类型。
- 这意味着在程序中,如果使用了某个基类型的对象,那么也可以用其子类对象来替换,且程序的行为不会发生变化。这是多态性的一个直接推论。
- 接口隔离原则(Interface Segregation Principle, ISP):
- 不应该强迫客户依赖于它们不使用的方法。
- 接口应该尽可能小,并且应该只包含客户端需要的方法。这样可以减少客户端与接口之间的耦合度,提高系统的灵活性和可维护性。
- 依赖倒置原则(Dependency Inversion Principle, DIP):
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
- 这条原则强调了通过接口或抽象类来解耦高层模块和低层模块之间的依赖关系,使得系统更加灵活和可扩展。
依赖倒置原则
依赖倒置原则(Dependency Inversion Principle, DIP)是面向对象设计五大基本原则之一,由罗伯特·C·马丁(Robert C. Martin)在《敏捷软件开发:原则、模式与实践》一书中提出。
这个原则的核心思想是:
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
这里的“高层模块”和“低层模块”是相对的,可以理解为在软件架构中,调用者(或使用者)和被调用者(或被使用者)的关系。高层模块通常是调用者,而低层模块是被调用者。
依赖倒置原则的关键点:
-
抽象化:通过接口或抽象类来定义高层模块和低层模块之间的交互,使得高层模块不直接依赖于低层模块的具体实现。
-
依赖抽象:高层模块和低层模块都依赖于抽象(接口或抽象类),而不是具体的实现类。这样,当低层模块的实现发生变化时,只要接口不变,高层模块就不需要修改。
-
细节依赖抽象:具体的实现类(细节)依赖于抽象接口,而不是反过来。这确保了系统的灵活性和可扩展性。
依赖倒置原则的好处:
- 降低耦合度:通过依赖抽象而不是具体实现,减少了模块之间的耦合度,使得系统更加灵活和可维护。
- 提高可测试性:由于高层模块不直接依赖于低层模块的具体实现,因此可以更容易地编写单元测试,模拟低层模块的行为。
- 提高可扩展性:当需要添加新的低层模块时,只要它符合高层模块所依赖的抽象接口,就可以无缝地集成到系统中,而不需要修改高层模块的代码。
示例
假设有一个日志系统,我们有一个Logger
接口和一个具体的FileLogger
实现类。我们的应用程序(高层模块)依赖于Logger
接口而不是FileLogger
类。这样,如果我们将来需要添加一个新的日志实现(如DatabaseLogger
),我们只需要实现Logger
接口,而不需要修改应用程序的代码。
// Logger接口(抽象)
public interface Logger {
void log(String message);
}
// FileLogger实现类(细节)
public class FileLogger implements Logger {
@Override
public void log(String message) {
// 将日志写入文件
}
}
// 应用程序(高层模块)
public class Application {
private Logger logger;
public Application(Logger logger) {
this.logger = logger;
}
public void doSomething() {
// 做一些事情
logger.log("Something happened");
}
}