# SOLID原则
# 1. S - 单一职责原则 (Single Responsibility Principle, SRP)
- 定义:一个类应该只有一个导致其变化的原因。
- 解释:每个类只应该有一个职责或功能,避免一个类承担过多的责任,从而使系统变得复杂和难以维护。每个职责变化都可能导致类的修改,因此将多个职责集中在一个类中会增加修改的复杂性。
- 示例:假设一个类既处理用户数据,又负责写日志,这违背了单一职责原则。我们应该将这两个功能拆分为独立的类,一个类只处理用户数据,另一个类负责日志记录。
# 2. O - 开放封闭原则 (Open/Closed Principle, OCP)
- 定义:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
- 解释:这意味着类应该能够在不修改现有代码的情况下进行扩展。通过继承或实现接口,新的功能可以被添加,而不需要修改已有的类,从而减少引入 bug 的可能性。
- 示例:假设你有一个订单处理系统,需要为不同类型的订单提供不同的处理方式。你可以使用一个基类,然后通过继承扩展新类型的订单处理逻辑,而不修改基类的代码。
# 3. L - 里氏替换原则 (Liskov Substitution Principle, LSP)
- 定义:子类对象必须能够替换父类对象而不会引发问题。
- 解释:如果 B 是 A 的子类,那么在应用程序中任何使用 A 的地方都可以无缝使用 B,不应该改变程序的正确性。违反里氏替换原则通常会导致子类的行为不一致,破坏代码的稳定性。
- 示例:如果一个类
Bird
有一个fly()
方法,而Penguin
是Bird
的子类,但企鹅不能飞,那Penguin
类不应该有fly()
方法。为了遵循 LSP,我们可以为飞行功能创建单独的接口,只有能够飞的鸟类才实现该接口。
# 4. I - 接口隔离原则 (Interface Segregation Principle, ISP)
- 定义:不应该强迫一个类去实现它不需要的接口。
- 解释:将大接口拆分为多个更小的、功能单一的接口,让类只实现它所需的功能接口,避免为实现不必要的接口方法而编写冗余代码。
- 示例:假设有一个
Worker
接口,包含work()
和eat()
方法。如果某些工人只需要work()
方法,不需要eat()
方法,那么应该将接口拆分为Workable
和Eatable
两个独立的接口,工人类可以根据需要选择实现哪个接口。
# 5. D - 依赖倒置原则 (Dependency Inversion Principle, DIP)
- 定义:高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
- 解释:通过依赖于抽象类或接口,而不是具体的实现类,能够减少模块之间的耦合,使代码更加灵活和可扩展。高层模块和底层模块之间通过接口或抽象类来解耦合。
- 示例:假设一个支付系统需要处理多种支付方式,如信用卡、PayPal 等。高层的订单模块不应直接依赖于某种具体的支付方式,而是应依赖于一个支付接口,不同的支付方式实现这个接口。这使得添加新支付方式时无需修改订单模块的代码。
# 总结
- SRP:类应该有且仅有一个原因引起变化。
- OCP:类应该可以扩展,但不应修改已有代码。
- LSP:子类必须能够替代父类。
- ISP:类不应该依赖它不使用的接口。
- DIP:依赖于抽象,而不是具体实现。
通过遵循 SOLID 原则,可以使代码更加模块化、可维护和可扩展,避免僵化、脆弱和不可扩展等常见设计问题。
系统分层 →