设计模式的六大原则有:(有些设计模式天生就符合这些原则,而有些设计模式可能会在特定情况下牺牲一些原则以获得其他优势)
Single Responsibility Principle:单一职责原则
Open Closed Principle:开闭原则
Liskov Substitution Principle:里氏替换原则
Law of Demeter:迪米特法则
Interface Segregation Principle:接口隔离原则
Dependence Inversion Principle:依赖倒置原则
把这六个原则的首字母联合起来(两个 L 算做一个)就是 SOLID (solid,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。下面我们来分别看一下这六大设计原则:
1.单一职责原则(Single Responsibility Principle)
一个类应该只有一个发生变化的原因。如果一个类负责处理用户输入数据的验证和数据库操作,那么这个类就违反了单一职责原则。因为用户输入数据的验证和数据库操作是两个不同的功能,应该由两个不同的类来负责
There should never be more than one reason for a class to change.
六大设计原则之单一职责原则(SRP)
2.开闭原则(Open Closed Principle)
一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭
Software entities like classes, modules and functions should be open for extension but closed for modification
六大设计原则之开闭原则(OCP)
3.里氏替换原则(Liskov Substitution Principle)
这个原则要求子类在被引用的地方能够替代其父类,而不会引起意外的行为或破坏程序的逻辑。换句话说,对于使用基类类型的代码来说,如果替换成子类对象后程序的行为仍然是正确的,那么这个子类就符合里氏替换原则。
Functions that use use pointers or references to base classes must be able to use objects of derived classes without knowing it.
六大设计原则之里氏替换原则(LSP)
4.迪米特法则(Law of Demeter)
迪米特法则要求在设计类的方法时,只应该调用以下对象的方法:
该对象本身
作为方法参数传递进来的对象
该对象直接创建的对象
该对象持有的成员对象
不应该直接调用全局对象、通过静态方法访问的对象、以及从其它方法返回的对象。这样做有助于降低类之间的耦合度,提高系统的灵活性和可维护性。
举个例子,如果一个类的方法需要调用另一个对象的方法,最好通过参数将该对象传递进来,而不是直接在方法中创建或引用这个对象。这样可以避免方法之间过度依赖,使得代码更加清晰、可读、可维护。
Talk only to your immediate friends and not to strangers
六大设计原则之迪米特法则(LOD)
5.接口隔离原则(Interface Segregation Principle)
客户端不应该依赖它不需要的接口:
这句话强调了在设计接口时应该避免将不相关或不需要的方法放在同一个接口中。如果一个客户端只需要使用接口中的部分方法,但是这个接口定义了很多其他不需要的方法,那么客户端就不应该依赖于这个接口。这样做可能会导致客户端需要实现不必要的方法,增加了代码的复杂性和维护成本。
类间的依赖关系应该建立在最小的接口上:
这句话强调了在类与类之间建立依赖关系时,应该使用最小的接口,即只提供被依赖类所需的方法。这样做可以降低类之间的耦合度,提高系统的灵活性和可维护性。如果一个类依赖于一个过大的接口,意味着它可能会受到不必要的影响,并且在接口发生变化时需要做出不必要的调整。
Clients should not be forced to depend upon interfaces that they don`t use.
The dependency of one class to another one should depend on the smallest possible.
六大设计原则之接口隔离原则(ISP)
6.依赖倒置原则(Dependence Inversion Principle)
上层模块不应该依赖底层模块,它们都应该依赖于抽象:
这句话强调了在系统设计中,高层模块(上层模块)和低层模块(底层模块)之间的依赖关系不应该直接存在,而是应该通过抽象来进行解耦。换句话说,高层模块和低层模块都应该依赖于抽象,而不是相互之间直接依赖。这样做可以提高系统的灵活性和可维护性,因为改变底层模块的实现不会影响到上层模块。
抽象不应该依赖于细节,细节应该依赖于抽象:
这句话强调了在使用抽象时,抽象不应该依赖于具体的实现细节,而是应该让具体的实现细节依赖于抽象。换句话说,抽象应该定义接口或者规范,而具体的实现细节则应该根据这个接口或规范来实现。这样做有利于降低耦合度,提高代码的可扩展性和可维护性,同时也方便了代码的替换和重用。
High level modules should not depend upon low level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.