天天看点

面向对象、设计模式之SOLID原则

solid

  solid 是面向对象设计5大重要原则的首字母缩写,当我们设计类和模块时,遵守 solid 原则可以让软件更加健壮和稳定。

这5大原则为:

单一职责原则(srp)

开放封闭原则(ocp)

里氏替换原则(lsp)

接口隔离原则(isp)

依赖倒置原则(dip)

另有6大原则版本:

single responsibility principle:单一职责原则

open closed principle:开闭原则

liskov substitution principle:里氏替换原则

law of demeter:迪米特法则

interface segregation principle:接口隔离原则

dependence inversion principle:依赖倒置原则

  设计模式把这6个原则的首字母联合起来(两个 l 算做一个)就是 solid (solid,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。下面我们来看一下里氏替换原则。

srp

  单一职责原则(single pesponsibility principle, srp),表明一个类有且只有一个职责。一个类就像容器一样,它能添加任意数量的属性、方法等。然而,如果你试图让一个类实现太多,很快这个类就会变得笨重。任意小的改变都将导致这个单一类的变化。当你改了这个类,你将需要重新测试一遍。如果你遵守 srp,你的类将变得简洁和灵活。每一个类将负责单一的问题、任务或者它关注的点,这种方式你只需要改变相应的类,只有这个类需要再次测试。srp 核心是把整个问题分为小部分,并且每个小部分都将通过一个单独的类负责。

  假设你在构建一个应用程序,其中有个模块是根据条件搜索顾客并以excel形式导出。随着业务的发展,搜索条件会不断增加,导出数据的分类也会不断增加。如果此时将搜索与数据导出功能放在同一个类中,势必会变的笨重起来,即使是微小的改动,也可能影响其他功能。所以根据单一职责原则,一个类只有一个职责,故创建两个单独的类,分别处理搜索以及导出数据。

ocp

  开放封闭原则(open closed principle,ocp),一个类应该对扩展开放,对修改关闭。这意味一旦你创建了一个类并且应用程序的其他部分开始使用它,你不应该修改它。为什么呢?因为如果你改变它,很可能你的改变会引发系统的崩溃。如果你需要一些额外功能,你应该扩展这个类而不是修改它。使用这种方式,现有系统不会看到任何新变化的影响。同时,你只需要测试新创建的类。

lsp

  里氏替换原则(liskov substitution principle,lsp),派生的子类应该是可替换基类的,也就是说任何基类可以出现的地方,子类一定可以出现。值得注意的是,当你通过继承实现多态行为时,如果派生类没有遵守lsp,可能会让系统引发异常。所以请谨慎使用继承,只有确定是“is-a”的关系时才使用继承。

lod

  迪米特法则(law of demeter,lod),也称为最少知道原则(least knowledge principle 简写lkp),一个对象应该对其他对象保持最少的了解。类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低。所以,在釆用迪米特法则时需要反复权衡,确保高内聚和低耦合的同时,保证系统的结构清晰。

isp

  接口隔离原则(interface segregation principle,isp),表明类不应该被迫依赖他们不使用的方法,也就是说一个接口应该拥有尽可能少的行为,它是精简的,也是单一的。客户端不应该被强迫实现一些他们不会使用的接口,应该把胖接口中的方法分组,然后用多个接口替代它,每个接口服务于一个子模块。简单地说,就是使用多个专门的接口比使用单个接口要好很多。

dip

  依赖倒置原则(dependence inversion principle,dip),表明高层模块不应该依赖低层模块,相反,他们应该依赖抽象类或者接口。这意味着你不应该在高层模块中使用具体的低层模块。因为这样的话,高层模块变得紧耦合低层模块。如果明天,你改变了低层模块,那么高层模块也会被修改。根据dip原则,高层模块应该依赖抽象(以抽象类或者接口的形式),低层模块也是如此。通过面向接口(抽象类)编程,紧耦合被移除。那么什么是高层模块,什么是低层模块呢?通常情况下,我们会在一个类(高层模块)的内部实例化它依赖的对象(低层模块),这样势必造成两者的紧耦合,任何依赖对象的改变都将引起类的改变。依赖倒置原则表明高层模块、低层模块都依赖于抽象。