软件设计的几大原则

设计模式 2015-07-28 7405浏览 收藏本文

软件设计原则是一系列的设计规范,它有助于开发人员做一个更加优秀的系统设计。这其中没重要的设计原则是SOLID设计原则。在实际的开发中,关键的软件设计原则有如下:

一、SOLID五大原则

SOLID是以下5个软件开发基本设计原则的简写,为了方便记忆,取每个原则的第一个字母组成,即:

1.单一职责原则(Single Responsibility Principle);
2.开放/封闭原则(Open/Closed Principle);
3.里氏替换原则(Liscov Substitution Principle);
4.接口隔离原则(Interface Segregation Principle);
5.依赖倒置原则(Dependency Inversion Principle)
那么这5个原则具体是什么呢?

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

此原则表现为:一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。此时,我们应该遵守单一职责原则,将不同的职责封装到不同的类或模块中。 例如,在媒体播放器中,可以在MediaPlayer类中定义一组与媒体播放相关的方法,如Open()、Play()、Stop()等。这些方法从职责的角度来讲,是内聚的,完全符合单一职责原则中"专注于做一件事"的要求。如果需求发生扩充,需要我们提供上传、下载媒体文件的功能。那么在设计时,就应该定义一个新类如MediaTransfer,由它来承担这一职责;而不是为了方便,草率地将其添加到MediaPlayer类中。

2.开放/封闭原则(Open/Closed Principle)

核心思想:对扩展开放,对修改封闭 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。 对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

3.里氏替换原则(Liscov Substitution Principle)

里氏替换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。 用法举例:假设您有一个继承层次结构的Person和Student类,无论什么地方可以使用Person类,你也应该可以使用Student类,因为Student是Person的子类。

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

接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上,使用多个专门的接口比使用单一的总接口要好。 用法举例: 比如说电子商务的系统,有订单这个类,有三个地方会使用到,一个是门户,只能有查询方法,一个是外部系统,有添加订单的方法,一个是管理后台,添加删除修改查询都要用到。 根据接口隔离原则(ISP),一个类对另外一个类的依赖性应当是建立在最小的接口上.也就是说,对于门户,它只能依赖有一个查询方法的接口。那么我们应该把订单的查询、添加、删除、修改操作接口分开来写,而不应该在一个总的接口里包含订单的所有操作。

5.依赖倒置原则(Dependency Inversion Principle)

要求客户端依赖于抽象耦合. (1)表述:抽象不应当依赖于细节,细节应当依赖于抽象.(Program to an interface, not an implementaction) (2) 表述二:针对接口编程的意思是说,应当使用接口和抽象类进行变量的类型声明,参量的类型声明,方法的返还类型声明,以及数据类型的转换等.不要针对实现编 程的意思就是说,不应当使用具体类进行变量的类型声明,参量类型声明,方法的返还类型声明,以及数据类型的转换等. 要保证做到这一点,一个具体的类应等只实现接口和抽象类中声明过的方法,而不应当给出多余的方法. 只要一个被引用的对象存在抽象类型,就应当在任何引用此对象的地方使用抽象类型,包括参量的类型声明,方法返还类型的声明,属性变量的类型声明等. (3) 接口与抽象的区别就在于抽象类可以提供某些方法的部分实现,而接口则不可以,这也大概是抽象类唯一的优点.如果向一个抽象类加入一个新的具体方法,那么所 有的子类型一下子就都得到得到了这个新的具体方法,而接口做不到这一点.如果向一个接口加入了一个新的方法的话,所有实现这个接口的类就全部不能通过编译 了,因为它们都没有实现这个新声明的方法.这显然是接口的一个缺点. (4)一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的登记结构中,而由于一般语言都限制一个类只能从最多一个超类继承,因此将抽象作为类型定义工具的效能大打折扣. 反过来,看接口,就会发现任何一个实现了一个接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个接口. (5)从代码重构的角度上讲,将一个单独的具体类重构成一个接口的实现是很容易的,只需要声明一个接口,并将重要的方法添加到接口声明中,然后在具体类定义语句中加上保留字以继承于该接口就行了. 而作为一个已有的具体类添加一个抽象类作为抽象类型不那么容易,因为这个具体类有可能已经有一个超类.这样一来,这个新定义的抽象类只好继续向上移动,变 成这个超类的超类,如此循环,最后这个新的抽象类必定处于整个类型等级结构的最上端,从而使登记结构中的所有成员都会受到影响. (6)接口是定义混合类型的理想工具,所为混合类型,就是在一个类的主类型之外的次要类型.一个混合类型表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为. (7)联合使用接口和抽象类: 由于抽象类具有提供缺省实现的优点,而接口具有其他所有优点,所以联合使用两者就是一个很好的选择. 首先,声明类型的工作仍然接口承担的,但是同时给出的还有一个抽象类,为这个接口给出一个缺省实现.其他同属于这个抽象类型的具体类可以选择实现这个接 口,也可以选择继承自这个抽象类.如果一个具体类直接实现这个接口的话,它就必须自行实现所有的接口;相反,如果它继承自抽象类的话,它可以省去一些不必 要的的方法,因为它可以从抽象类中自动得到这些方法的缺省实现;如果需要向接口加入一个新的方法的话,那么只要同时向这个抽象类加入这个方法的一个具体实 现就可以了,因为所有继承自这个抽象类的子类都会从这个抽象类得到这个具体方法.这其实就是缺省适配器模式(Defaule Adapter). (8)什么是高层策略呢?它是应用背后的抽象,是那些不随具体细节的改变而改变的真理. 它是系统内部的系统____隐喻.

二、合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)

在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过这些向对象的委派达到复用已有功能的目的.这个设计原则有另一个简短的表述:要尽量使用合成/聚合,尽量不要使用继承.

三、迪米特法则(Law of Demeter LoD)

又叫做最少知识原则(Least Knowledge Principle,LKP)就是说,一个对象应当对其他对象有尽可能少的了了解. 迪米特法则最初是用来作为面向对象的系统设计风格的一种法则,与1987年秋天由Ian Holland在美国东北大学为一个叫做迪米特(Demeter)的项目设计提出的,因此叫做迪米特法则[LIEB89][LIEB86].这条法则实际 上是很多著名系统,比如火星登陆软件系统,木星的欧罗巴卫星轨道飞船的软件系统的指导设计原则. 没有任何一个其他的OO设计原则象迪米特法则这样有如此之多的表述方式,如下几种: (1)只与你直接的朋友们通信(Only talk to your immediate friends) (2)不要跟"陌生人"说话(Don't talk to strangers) (3)每一个软件单位对其他的单位都只有最少的知识,而且局限于那些本单位密切相关的软件单位. 就是说,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

转载请注明:图享网 » 软件设计的几大原则

验证码