目录
里氏替换原则(Liskov Substitution Principle, LSP)
前言
在学习设计模式之前,我们要先了解设计模式的设计原则,经典的23种设计模式中或多或少地都在使用这些设计原则。设计模式都是站在设计原则的基础之上的。让我们开始设计原则的学习之旅吧。
单一职责原则
1. 引言
单一职责原则(Single Responsibility Principle, SRP)是面向对象设计中的一个重要原则。它强调一个类应该只有一个引起其变化的原因,即一个类只负责一项职责。这样做可以提高类的内聚性和可维护性,使代码更易于理解、扩展和修改。
2. 单一职责原则的定义
单一职责原则可以简单地定义为:一个类只负责完成一个功能或者承担一个责任。换句话说,一个类应该有且只有一个理由来进行修改。
3. 为什么要遵守单一职责原则?
3.1 提高代码的可维护性
当一个类只负责一项职责时,它的代码逻辑会更加清晰和简洁。如果一个类包含多个不相关的职责,那么在修改其中一个职责时,很可能会影响到其他职责的实现。而遵守单一职责原则可以降低代码的复杂度,使得代码更易于理解和维护。
3.2 提高代码的复用性
遵守单一职责原则可以使得类的功能更加独立,降低了类之间的耦合度。这样一来,在需要使用某个功能的时候,可以单独引用该功能所属的类,而无需引入其他不相关的功能。这可以提高代码的复用性,减少重复代码的编写。
3.3 提高系统的灵活性和可扩展性
当一个类负责多个职责时,增加新的职责或者修改已有的职责可能会影响到其他部分的代码。而遵守单一职责原则可以将不同的职责分离开来,使得系统的各个部分之间相互解耦。这样一来,新增功能或者修改功能时,只需要修改与该功能相关的类即可,不会影响到其他类的代码。这提高了系统的灵活性和可扩展性。
4. 如何遵守单一职责原则?
4.1 分析类的职责
在设计和编写类之前,需要明确该类的职责是什么。一个类应该只有一个引起其变化的原因,即它应该只负责一项功能或者承担一个责任。
4.2 封装不同的职责
根据类的职责,将相关的属性和方法封装到一个类中。不同的职责应该由不同的类来承担,每个类专注于完成自己的职责。
4.3 避免违反单一职责原则的情况
在设计和编写代码时,需要注意避免将不相关的职责放在同一个类中。如果发现一个类负责的职责过多,可以考虑进行拆分,将不相关的职责封装到其他类中。
5. 总结
单一职责原则是面向对象设计中的重要原则之一,它强调一个类应该只有一个引起其变化的原因,即一个类只负责一项职责。遵守单一职责原则可以提高代码的可维护性、复用性和系统的灵活性。在设计和编写代码时,我们应当分析类的职责,封装不同的职责,并避免违反单一职责原则的情况的发生。这样可以使得代码更易于理解、扩展和修改,提高软件系统的质量和可维护性。
开放封闭原则
1. 什么是开放封闭原则
开放封闭原则(Open-Closed Principle,OCP)是面向对象设计中的一个重要原则,它由Bertrand Meyer提出。开放封闭原则指导我们设计软件模块时应该对扩展开放,对修改封闭。也就是说,当需求发生变化时,我们应该通过扩展现有的代码来实现变化,而不是直接修改已有的代码。
2. 为什么要遵守开放封闭原则
遵守开放封闭原则可以带来以下好处:
- 可维护性:当需求变化时,我们只需要新增代码而不是修改已有的代码,这样可以减少引入新错误的风险,并且不会影响到已经稳定运行的代码。
- 可扩展性:通过扩展现有的代码,我们可以实现新的功能,而不需要修改已有的代码,这样可以降低系统的耦合度,提高代码的复用性。
- 可测试性:由于对已有代码的修改减少,我们只需要关注新增的代码是否符合要求,这样可以更加方便地进行单元测试和集成测试。
3. 如何遵守开放封闭原则
为了遵守开放封闭原则,我们可以采取以下几种设计模式和技术手段:
3.1 使用接口和抽象类
通过定义接口和抽象类,我们可以将系统中的各个模块进行解耦,每个模块只依赖于接口或抽象类,而不依赖于具体的实现。当需求变化时,我们只需要新增实现接口或继承抽象类的类,而不需要修改已有的代码。
3.2 使用多态
多态是面向对象编程的重要特性,它可以使得程序在运行时根据对象的实际类型来调用相应的方法。通过使用多态,我们可以将不同的行为封装在不同的类中,当需求变化时,我们只需要新增相应的类,而不需要修改已有的代码。
3.3 使用设计模式
设计模式是一些被广泛接受的解决特定问题的经验总结,它们可以帮助我们遵守开放封闭原则。常用的设计模式包括策略模式、观察者模式、装饰器模式等。通过使用设计模式,我们可以将变化的部分封装成独立的类,从而实现对修改的封闭和对扩展的开放。
4. 总结
开放封闭原则是面向对象设计中的重要原则,它要求我们对扩展开放,对修改封闭。遵守开放封闭原则可以提高代码的可维护性、可扩展性和可测试性。为了遵守开放封闭原则,我们可以使用接口和抽象类、多态以及各种设计模式等技术手段。通过不断实践和总结,我们可以更好地理解和应用开放封闭原则,设计出高质量的软件系统。
里氏替换原则(Liskov Substitution Principle, LSP)
1. 引言
里氏替换原则是面向对象设计中的一个重要原则。它强调子类型(派生类)必须能够替换掉它们的父类型(基类)并且程序仍然能够正常工作,即子类型应该能够完全替代父类型的行为。这一原则可以提高代码的可扩展性、复用性和可维护性。
2. 里氏替换原则的定义
里氏替换原则可以简单地定义为:如果S是T的子类型,那么在任何T类型可以使用的地方,都可以用S类型来替换,而不会导致程序出错或产生异常。换句话说,子类型必须能够保持父类型的接口规范、约束和行为,并且可以添加自己特有的功能。
3. 为什么要遵守里氏替换原则?
3.1 提高代码的可扩展性
遵守里氏替换原则可以使得系统更易于扩展。当新增一个子类型时,只需关注子类型特有的功能实现,而无需修改已经存在的代码。这种可扩展性可以减少代码的耦合度,使得系统具备更好的模块化和可维护性。
3.2 提高代码的复用性
里氏替换原则要求子类型能够完全替代父类型,这意味着可以在不修改现有代码的情况下,通过替换父类型为子类型来实现新的功能。这种代码的复用性可以减少重复代码的编写,提高代码的效率和质量。
3.3 保证系统的正确性和稳定性
如果一个子类型无法完全替换父类型的行为,那么在程序中使用该子类型可能会导致错误或异常的发生。遵守里氏替换原则可以确保各个子类型在使用时能够正确地执行父类型的行为,从而保证系统的正确性和稳定性。
4. 如何遵守里氏替换原则?
4.1 符合里氏替换原则的条件
子类型必须满足以下条件才能够完全替换父类型:
4.1.1 子类型的前置条件必须比父类型更宽松或者相等
子类型接收的输入参数必须比父类型更宽松,即子类型的前置条件比父类型更弱。这可以保证子类型在使用时不会引入额外的限制。
4.1.2 子类型的后置条件必须比父类型更严格或者相等
子类型的输出结果必须比父类型更严格,即子类型的后置条件比父类型更强。这可以保证子类型在使用时不会破坏父类型约定的行为。
4.2 避免违反里氏替换原则的情况
在设计和编写代码时,需要注意避免以下情况,以防止违反里氏替换原则:
4.2.1 子类型修改或者限制了父类型的行为
子类型在重写父类型的方法时,不应该修改父类型已经定义的行为。如果子类型修改了父类型的行为,可能会导致在程序中使用子类型时发生错误或异常。
4.2.2 子类型违反了父类型的约束和规范
子类型在实现接口或继承抽象类时,必须遵守父类型定义的约束和规范。如果子类型无法满足父类型的约束和规范,可能会导致在程序中使用子类型时产生意想不到的结果。
5. 总结
里氏替换原则是面向对象设计中的重要原则之一,它强调子类型必须能够替换掉父类型并且程序仍然能够正常工作。遵守里氏替换原则可以提高代码的可扩展性、复用性和系统的正确性和稳定性。在设计和编写代码时,我们应当符合里氏替换原则的条件,避免违反该原则的情况的发生。这样可以使得代码更易于扩展和维护,提高软件系统的质量和可维护性。
4、迪米特法则
理解:尽量减少对象之间的交互,从而减小类之间的耦合。在做系统设计时,不要让一个类依赖于太多其他的类,需尽量减小依赖关系,否则死都不知道怎么死的。
总结:一定要做到:低耦合、高内聚。
5、接口分离原则
理解:不要对外暴露没有实际意义的接口。也就是说,尽量保证接口的实用性。当需要对外暴露接口时,需要再三斟酌,若没必要对外提供就删了吧,因为一旦提供了就意味着,将来要多做一件事情,何苦给自己找事做呢。
总结:不要对外暴露没有实际意义的接口。
6、依赖倒转原则
理解:高层模块不应该依赖于底层模块,而应该依赖于抽象。抽象不应依赖于细节,细节应依赖于抽象。应该面向接口编程,不该面向实现类编程。面向实现类编程相当于就事论事,那是正向依赖;面向接口编程,相当于透过现象看本质,抓住事务的共性,那就是反向依赖,即依赖倒置。
总结:面向接口编程,提取出事务的本质和共性。
将六大原则的英文首字母拼在一起就是SOLID(稳定的),所以也称之为SOLID原则。