面向对象设计7大原则

Posted by Don on September 27, 2019

对于面向对象软件,其可维护性和可复用性是2个非常重要的用于衡量软件质量的条件,那么如何提高一个软件的可维护性和可复用性呢?这就是本篇文章的主题————面向对象设计的7大原则,或者称之为设计模式7大原则,因为每个设计模式都符合一个或多个面向对象设计原则。

1.单一职责原则 Single Responsibility Principle(SRP)

定义: 一个对象应该只包含一个单一的职责,并且该职责被完整的封装在一个类中

在一个软件系统中,一个类的职责越多,它被复用的可能行就越小,而且一个类承担的职责越多,就相当于职责耦合在一起,所以要将这些职责进行分离,将不同的职责分装在不同的类中,因此单一职责的原则是为了实现高内聚、低耦合

2.开闭原则 Open-Closed Principle(OCP)

定义: 软件实体应该对扩展开放,对修改关闭

开闭原则是指软件应该在不修改原有代码的情况下进行扩展,那么如何能不在修改源代码的情况下进行扩展呢?那就需要对系统进行抽象化设计,我们可以利用接口、抽象类等机制设计抽象层,将不同的实现行为移至具体的实现层中就完成。那么如果需要修改系统的行为,我们无需对抽象层进行任何改动,只需要增加新的具体类来实现新的业务即可。

3.里氏代换原则 Liskov Substitution Principle(LSP)

定义: 所有引用基类的地方必须能透明的使用其子类的对象。

里氏代换原则是实现开闭原则的基础。在程序中应尽量使用基类类型对对象进行定义,运行时再确定其子类类型,用子类对象来替换父类对象。

4.依赖倒转原则 Dependency Inversion Principle(DIP)

定义: 高层模块不应该依赖低层模块,它们都应该依赖抽象

简单来说,依赖倒转原则要求要针对接口编程,不要针对实现编程。 在代码中传递参数或者关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型的声明、参数类型的声明,方法返回类型声明,以及数据类型的转换等。为了确保该原则的应用,一个具体类应该只实现接口或抽象类中声明的方法,而不要给出多余的方法,否者将无法调用到子类中新增加的方法。

在实现依赖倒转原则时,需要针对抽象层进行编程,而将具体类的对象通过依赖注入的方式注入到其他对象中。依赖注入是指当一个对象要与其他对象发生依赖关系时,通过方法参数来注入所依赖的对象。常用的注入方式有3种,分别是构造注入(构造方法传参),设值植入(Setter注入)和接口注入(接口中声明业务方法)。这些方法在定义时使用的是抽象类型,在运行时再传入具体类型的对象,由子类对象来覆盖父类对象。

5.接口隔离原则 Interface Segregation Principle(ISP)

定义: 客户端不应该依赖那些它不需要的接口

每一个接口应该承担一种相对独立的角色,只干应该要干的事。
在使用接口隔离原则时,需要注意控制接口的粒度,接口太小,会导致项目中接口泛滥,不利于维护;接口太大会违背接口隔离原则,灵活性较差,使用起来很不方便。

6.合成复用原则 Composite Reuse Principle(CRP)

定义: 优先使用对象组合,而不是继承来达到复用的目的。

复用时要尽量使用组合/聚合关系,少用继承。 原因如下:

  1. 继承会破坏系统的封装性,因为继承会将基类的实现细节暴露给子类;而且基类发生改变后子类的实现也不得不改变
  2. Java只能单继承

7.迪米特法则 Law of Demeter(LoD)

定义: 每一个软件单位对其他的单位都只有最少的知识,而且局限与那些与本单位密切相关的软件单位。

迪米特法则要求一个软件实体尽可能少的与其他实体发生相互作用,这样可以降低系统的耦合度,使类与类之间保持松散的耦合关系。