软件设计原则
软件设计原则又简称为 SOLID 原则,设计模式主要是基于 OOP 编程提炼的,它基于以下几个原则。
单一职责原则
单一职责原则(Single Responsibility Principle,SRP)是指一个类只负责一个功能领域中的职责,或者可以定义为一个类只有一个引起它变化的原因,否则类应该被拆分。如果一个类承担了过多的职责,就可能导致代码的耦合度过高,难以维护和扩展。这个原则的目的是将一个类的职责分解为多个独立的类,这样可以提高类的内聚性,降低它们的耦合性,提高类的复用性。
开闭原则
开闭原则(Open-Closed Principle,OCP)是指一个软件实体(如类、模块和函数)应该对扩展开放,对修改关闭。这意味着一个软件实体应该通过扩展来实现新的功能,而不是通过修改已有的代码来实现。这个原则的目的是使软件实体在不修改的情况下可以被扩展,以满足新的需求。实现开闭原则的核心思想是面向抽象编程,用抽象构建框架,用实现扩展细节。例如,我们可以使用抽象类或接口来定义一个通用的框架,然后通过继承或实现来添加新的功能,而不是直接修改已有代码。
里氏替换原则
里氏替换原则(Liskov Substitution Principle,LSP)是指一个对象应该可以被它的子类替换,而不影响程序的正确性。这意味着一个软件实体应该在任何使用基类(父类)的地方都可以替换成子类,而不必改变程序的逻辑。这个原则的目的是保证继承关系正确使用,避免继承导致的问题。实现里氏替换原则的关键是抽象化,抽象化是面向对象编程的核心思想,它可以通过接口或抽象类来实现。例如,我们可以使用接口或抽象类来定义一个通用的规范,然后通过实现来提供具体的功能,而不是直接使用具体的实现类。
依赖倒置原则
依赖倒置原则(Dependency Inversion Principle,DIP)是指高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于具体,具体应该依赖于抽象。这意味着一个软件实体应该通过抽象接口来与依赖对象通信,而不是直接依赖于具体实现。这个原则的目的是降低模块之间的耦合度,提高系统的稳定性和可维护性。实现依赖倒置原则的关键是面向接口编程,通过接口来定义规范,然后通过实现来提供具体的功能。例如,我们可以使用接口来定义一个通用的规范,然后通过实现来提供具体的功能,而不是直接使用具体的实现类。
接口隔离原则
接口隔离原则(Interface Segregation Principle,ISP)是指一个类对另一个类的依赖应该建立在最小的接口上。这意味着一个类不应该依赖于它不需要的接口,或者说一个类对另一个类的依赖应该建立在最小的接口上。实现接口隔离原则的关键是定义多个小而专用的接口,而不是定义一个大而全的接口。这个原则的目的是降低类之间的耦合度,提高系统的灵活性和可维护性。
迪米特法则
迪米特法则(Law of Demeter,LoD)又称为最少知道原则(Least Knowledge Principle,LKP),是指一个对象应该对其他对象有尽可能少的了解,也就是说一个对象应该对其他对象有尽可能少的依赖。如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。迪米特原则主要强调只和朋友交流,不和陌生人说话。出现在成员变量、方法的输入、输出参数中的类都可以称之为成员朋友类,而出现在方法体内部的不属于朋友类。实现迪米特法则的关键是封装,封装是面向对象编程的核心思想,它可以通过接口或抽象类来实现。其目的是降低类之间的耦合度,提高模块的相对独立性。
组合/聚合(合成)复用原则
组合/聚合(合成)复用原则(Composite/Aggregate Reuse Principle,CARP)是指尽量使用组合或聚合关系来实现对象的复用,而不是使用继承关系来实现。这意味着一个软件实体应该优先通过组合或聚合来实现代码复用,而不是通过继承来实现。继承我们叫做白箱复用,相当于把所有的实现细节暴露给子类,组合/聚合也称为黑箱复用,对类以外的对象是无法获取到实现细节的。如果子类与父类的耦合度高,父类的任何改变都会导致子类的实现发生变化,这不利于类的扩展。这个原则的目的是降低类之间的耦合度,提高系统的灵活性和可维护性,一个类的变化对其他类造成的影响相对较少。例如,我们可以将一个复杂的功能拆分成多个简单的类或模块,然后通过组合的方式来实现这个功能。
总结
其实上面这些原则都有一个共同的目标,就是尽量面向抽象编程,降低类之间的耦合度,提高系统的灵活性、可扩展性和可维护性。强调面向对象编程的核心思想,即抽象、封装、继承和多态。
软件设计原则是面向对象编程的基础,它们是设计模式的基石,是编写高质量代码的关键。这些原则可以帮助我们编写出更加灵活、可维护、可扩展的代码,提高代码的质量和效率。在实际开发中,我们应该遵循这些原则,尽量将它们应用到我们的代码中,以提高代码的质量和效率。但是,这些原则并不是一成不变的,它们是相互关联、相互影响的,我们应该根据具体的情况来灵活运用这些原则,以满足实际需求,而不是教条地遵循这些原则。