设计模式之SOLID原则

介绍

设计模式中的SOLID原则,分别是单一原则、开闭原则、里氏替换原则、接口隔离原则、依赖倒置原则。前辈们总结出来的,遵循五大原则可以使程序解决紧耦合,更加健壮。

                SRP

                        单一责任原则

                OCP

                        开放封闭原则

                LSP

                        里氏替换原则

                 ISP

                        接口隔离原则

                 DIP

                        依赖倒置原则

思维导图:从封装、继承的角度考虑七大原则的关系:

设计模式之SOLID原则_第1张图片

 

单一职责原则(Single Responsibility Principle):

定义:就一个类而言,应该仅有一个引起它变化的原因。 

优点:

  1. 类的复杂性降低。类的职责单一,复杂性自然就降低了。
  2. 可读性高。
  3. 易维护。
  4. 变更引起的风险降低。

 

开放封闭原则(open closed principle):

开闭原则(OCP)是面向对象设计中“可复用设计”的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段。

定义:软件实体(类、模板、函数等等)应该可以扩展,但是不可修改。

简单的说就是,当一个软件实体需要扩展的时候,不要去修改原有的代码,而是去扩展原有的代码。其实开闭原则是最基础的一个原则,下面六个原则都是开闭原则的具体形态。

特点:

  • 对于拓展是开放的(open for extension)
  • 对于更改是封闭的(closed for modification)

使用开闭原则的理由:

第一:开闭原则非常有名,只要是面向对象编程,在开发时都会强调开闭原则

第二:开闭原则是最基础的设计原则,其它的五个设计原则都是开闭原则的具体形态,也就是说其它的五个设计原则是指导设计的工具和方法,而开闭原则才是其精神领袖。依照java语言的称谓,开闭原则是抽象类,而其它的五个原则是具体的实现类。

第三:开闭原则可以提高复用性 

在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来,不是在一个类中独立实现一个业务逻辑。只有这样的代码才可以复用,粒度越小,被复用的可能性越大。那为什么要复用呢?减少代码的重复,避免相同的逻辑分散在多个角落,减少维护人员的工作量。那怎么才能提高复用率呢?缩小逻辑粒度,直到一个逻辑不可以分为止。

第四:开闭原则可以提高维护性 

一款软件量产后,维护人员的工作不仅仅对数据进行维护,还可能要对程序进行扩展,维护人员最乐意的事是扩展一个类,而不是修改一个类。让维护人员读懂原有代码,再进行修改,是一件非常痛苦的事情,不要让他在原有的代码海洋中游荡后再修改,那是对维护人员的折磨和摧残。

第五:面向对象开发的要求 

万物皆对象,我们要把所有的事物抽象成对象,然后针对对象进行操作,但是万物皆发展变化,有变化就要有策略去应对,怎么快速应对呢?这就需要在设计之初考虑到所有可能变化的因素,然后留下接口,等待“可能”转变为“现实”。

 

里氏替换原则(LSP liskov substitution principle):

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

继承的优点:

  1. 代码共享,提高代码的重用性。
  2. 提高代码的可扩展性。
  3. 提高产品或者项目的开放性。

继承的缺点:

  1. 继承是侵入式的,只要继承,就拥有了父类的属性和方法。
  2. 降低代码灵活性,子类拥有了父类的属性和方法,多了一些约束。
  3. 增强了耦合性。父类的常量、变量或方法改动时,必须还要考虑子类的修改,可能会有大段代码需要重构。

里氏替换原则四层含义:

  1. 子类必须完全实现父类的方法
    在类中调用其他类时务必使用父类或接口,如若不能,则说明类的设计已经违背LSP原则。
    如果子类不能完整的实现父类的方法,或者父类的方法在子类中发生畸变,这建议断开父子继承关系,采用依赖、聚集、组合等方式代替继承。
  2. 子类可以有自己的特性:即子类出现的地方父类未必可以出现。
  3. 覆盖父类的方法时输入参数可以被放大:输入参数类型宽于父类的类型的覆盖范围,例如 hashmap -> map。
  4. 覆盖父类的方法时输出参数可以被缩小

 

接口隔离原则(interface segregation principle)

定义:客户端不应该依赖他不需要的接口,类之间的依赖关系应该建立在最小的接口上。

四层含义:

  1. 接口尽量要小,不要出现臃肿的接口。
  2. 接口要高内聚。
  3. 只提供访问者需要的方法:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。
  4. 接口设计是有限度的:接口设计粒度越小,系统越灵活。但是结构会越复杂、开发难度增加,可维护性降低。

 

依赖倒置原则(dependence inversion principle)

      面向接口编程;(通过接口作为参数实现应用场景)

  理解:抽象就是接口或者抽象类,细节就是实现类

  两层含义:

    上层模块不应该依赖下层模块,两者应依赖其抽象;

    抽象不应该依赖细节,细节应该依赖抽象;

 

 

第六大原则:

迪克特法则(最少知道原则)(Least Knowledge Principle,LKP)

定义:一个对象应该对其他对象有最少的了解(低耦合)。

三层含义:

  1. 一个类只与朋友交流,不和陌生类交流,方法尽量不引入类中不存在的对象。
  2. 尽量不要对外暴露过多的 public 方法和非静态的 public 变量,尽量内敛。
  3. 自己的就是自己的。如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,那就放置在本类中。

总结:
    迪米特法则的核心观念就是类间解耦,低耦合。其负面影响就是产生了大量的中转或者跳转类,导致系统复杂性提高,也为维护带来了难度。需要反复权衡,既做到结构清晰,又要高内聚低耦合。
如果一个类需要跳转两次以上才能访问到另一个类,就需要想办法重构了。

 

 

你可能感兴趣的:(#,C#设计模式)