经过不到一个月的时间终于把《大话设计模式》这本书看完了,从一个一个的小故事引出的设计模式,让我眼花缭乱,无从下手,就从这6个基本原则说起吧。设计模式的基本原则保证了设计出来的软件的灵活性,可复用性,可扩展性。它就像一套规则,给设计加以一定的约束。它是评判软件设计好坏的标准。
1 单一职责原则
1.1定义
(SRP:Single Responsibility Principle),就一个类而言,应该仅有一个引起它变化的原因
1.2 理解
单一职责其实很好理解,就是一个类的功能尽可能只有一个,如果把许多功能放到一起,功能之间的耦合度非常高,必定相互影响。如果要变更需求,那么要改动的地方就非常的多。这样的类维护起来很困难,也几乎不可能得到复用,软件缺乏灵活性。例如:我之前画机房收费系统,有一个类是User,职责有登录,修改密码,显然这违背了单一职责原则,登录和修改密码这两个功能是相互影响的,修改了其中一个,另一个的功能有可能就不能正常运行。这是最基本的一个原则,在软件中处处体现。
2 开闭原则
2.1定义
软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。
2.2理解
对于扩展是开放的,对于更改是关闭的。遵循开-闭原则使软件在面对需求的变更时,可以保持相对的稳定,系统可以在第一个版本后不断推出新的版本。
这个原则的引出是因为软件开发过程中,需求是不断变更的,这就需要修改旧的代码,甚至进行重构,所以在设计阶段,就要求设计人员在设计模块的时候,猜测最有可能发生变化的种类,然后构造抽象来隔离这些变化。但是计划赶不上变化,肯定有很多变化是我们无法预料的,当面对这些不可控的变化时,我们就要创建抽象来隔离以后同类的变化。
对代码的改动,是指扩展新的代码,而不是更改现有的代码。其实遵循这个原则不难,就是考验了设计人员的对于变化频繁的那部分的抽象能力。看了很多人的博客,有一个人的一条评论点醒了我,他说:“开闭的真正作用是在设计阶段,封装变化点,预留扩展。”
3 依赖倒转原则
3.1定义
A.高层模块不应该依赖低层模块。两个都应该依赖抽象
B.抽象不应该依赖细节。细节应该依赖抽象。换言之:要针对接口编程,不要对实现编程
3.2理解
倒转的意思是在软件开发过程中,高层模块要依赖于底层模块,例如模块调用子模块,调用底层函数等等。面向接
口编程的意思是,当需求发生变化时,先考虑抽象,接口的方面,不要考虑具体实现。正如书中举得例子,电脑内存坏了,换一个就好,不会影响其他硬件的工作。因为接口是相同的,只要接口稳定,任何变更都不用担心其他收到影响。感觉这个原则保证了软件的“高内聚低耦合”。
4 里氏代换原则
4.1定义
(LSP:Liskov Substitution Principle) 子类型必须能够替换掉他们的父类型。换言之,在软件里面,把父类都替换成他的子类,程序的行为没有变化。
4.2理解
这个原则使得继承复用成为可能,只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。这是实现开闭原则的方式之一,上边讲到了,开闭原则主要是把频繁变化的部分抽象,而基类大部分都是抽象类或者接口。当子类继承基类的时候,我们用子类替换掉父类,很容易在子类的基础上扩展功能。
看刘伟关于这部分的博客里边有一段话说的很好,关于开-闭、依赖倒转、里氏代换三个原则之间的关系:
在大多数情况下,这三个设计原则会同时出现,开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段,它们相辅相成,相互补充,目标一致,只是分析问题时所站角度不同而已。
5 迪米特
5.1定义
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的偶一个方法的话,可以通过第三者转发这个调用。
5.2理解
首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。这个原则体现的是封装的思想,迪米特的根本思想就是强调了类之间的松耦合关系。耦合强度弱了,就越容易被复用。例如:第一次做机房的时候,设计到很多按钮,列表,窗体的类,他们之间存在着或多或少的联系,类与类之间能产生很多信息的传递,这样就违背了迪米特法则,如果加一个传递参数的中间类,这样他们之间的联系就没有了,所有类之和中间类产生关联就好了。
6 合成聚合复用
6.1定义
(Composite Reuse Principle, CRP):尽量使用合成/聚合,而不是使用类的继承来达到复用的目的
6.2理解
聚合表示一种弱的“拥有”关系,体现的是包含关系,比如雁群包含很多只大雁;合成表示强的“拥有”关系,体现严格的部分和整体的关系,部分和整体有相同的而生命周期,比如大雁和翅膀就是合成关系。
软件编程时应尽量应用组合/聚合关系,这样做出来的类与类之间的耦合较低,如果使用继承关系,父类与子类有非常紧密的依赖关系,父类如果改变,子类就要相应改变。如果要复用子类,但是功能不全,就要修改已经写好的父类。这种依赖关系限制了灵活性最终限制复用性。
7 总结
在6个原则的约束下,我们才能创造出不同的设计模式,但是不是每一个设计模式都符合所有的原则,模式之间各有优缺点,这也是为什么会有如此多的模式的出现。其实6个原则都是为了让我们设计出来的软件具有灵活性,可维护性,可扩展性,复用性好的特点。所以我们要熟练记住这些基本原则,再设计中才能熟练应用。