软件设计中的几点设计原则(上)

wangcaipang 2010-01-24

最近又翻起阎宏博士的《Java与模式》这本书,此书语言浅显易懂,且内容充实,值得反复阅读思考,就像好的电影都会让你想有时间再翻出来再看看,此书也是一样。

翻阅之中,觉得还是把内容摘抄下来,一是避免捧着这本大块头的痛苦,二是便于自己整理思路。

以下内容大部分摘自此书的第二部分。

什么情况下一个软件系统会变得“腐烂”:

1.僵硬:增加新功能要影响很多地方。

2.脆弱:一个地方的修改,会导致其他地方的发生变化或者故障。

3.复用率低:代码、函数等难以被程序员复用在软件的其他地方.

导致程序员重复造轮子,甚至cp&paste来使用已有代码。

4.粘度过高:当一个改动,可以按照原有设计框架进行,也可以另辟蹊径快速解决。

当第二种情况出现,则表示原系统设计粘度过高!

设计的目标:

1.Extensibility可扩展性:与“僵硬”相反,一个功能可以很容易的加入到系统中去,并尽量少的影响其他功能

2.Flexibility灵活性:与扩展性的增加功能相比来,当代码的修改,可以平稳发生,不会波及到其他模块,即与“脆弱”相反

3.Pluggability可插入性:系统设计的接口和实现体,能够满足开发者很方便的替换来修改系统的功能。

从而避免脱离原设计框架的改动方式,进而避免“粘度过高”现象的出现。

即经常出现脱离系统设计框架的“开发捷径”。

设计原则:

1.开闭原则(Openforextension,closeformodification)

诚如标题解释的一样:对扩展开放,对修改封闭。在不被修改的情况下扩展,在不被修改的情况下行为产生变化。

对可变性封装的原则:

A.一种可变性不应当散落在很多地方,应该被封装在一个对象里。

B.一种可变性不应该与另一种可变性混合在一起。从这一点上来说,类的继承结构不应该超过2层,不然就意味着2中不同的可变性混合在一起。

这里的2层,我(马背)自己的理解可以解释成具体类实现一个接口的2层,可以可以从继承的角度来看,即从接口-》抽象类-》具体实现类这样的2层“继承”。当然这里的抽象类可以是多级结构,但只是在封装了相同的行为,不影响总体上的2层结构

从2层的结构中我们也可以看出抽象类一定是用来继承的,而具体类则不是用来继承的,并且应该优先使用接口声明类型。

继承应该被看做封装变化的方法,而不是从一般对象到特殊对象的方法。

2.里氏替换原则(Liskovsubstitutionprinciple)

任何基类被子类替换后,整个应用的功能没有变化(行为产生变化)。

但反过来的代换是不成立的。

由于Liskov替换原则主要讲基类与子类的关系,这里也说一下继承关系使用的条件

A.区分好子类是不是超类的一个“角色”,即只有"Is-A"的关系才符合。

"Has-A"则应用使用聚合关系描述。

B.子类不会出现成为其他类子类的可能行。

C.子类具体扩展超类的责任,但不是置换掉(Override)或者注销掉(Nullify)超类的责任

D.从分类学上有意义时候使用继承,不要从工具类继承。

当有继承关系的两个类A、B不符合Liskov原则时候,一般有2中方法来解决:

A.为2者抽象出一个超类,并使二者的共同行为移到新的超类中。

B.把B继承与A改为委派关系,即B拥有A的实例。

未完待续。。。

马背{eric.liu}

2010.1.24

相关推荐

Zhongmeishijue / 0评论 2014-11-21

CherrylinORC / 0评论 2015-05-02