我们生活在一个充满规则的世界里,在复杂多变的外表下,万事万物都被永恒的真理支配并有规律的运行着。模式也是一样,不论那种模式,其背后都潜藏着一些“永恒的真理”,这个真理就是设计原则。
那天在网上查东西,偶然看到一段话:记得一次参加微软的架构师培训,期间讲到设计 模式,有人问了老师一个问题:“什么东西比设计模式更重要?”,老师是一位有多年丰富实践经验的开发者,他毫不犹豫地回答到:“比模式更重要的是原则”。
这句话我时常能够想起,越来越觉得这是一个伟大的答案。的确,还有什么比原则更重要呢?就像人的世界观和人生观一样,那才是支配你一切行为的根本,而对于设计模式来说,为什么这个模式要这样解决这个问题,而另一个模式要那样,它们背后都遵循的就是永恒的设计原则。可以说,设计原则是设计模式的灵魂。
一:设计模式的核心原则是:"开-闭"原则
一切的一切都是围绕着"开-闭"原则展开的
开闭原则:说软件实体(类,模块,函数等)应该可以扩展,但是不可以修改 [DH].意思是,在一个系统中,对于扩展是开放的,对于修改是关闭的,一个好的系统是在不修改源代码的情况下,可以扩展你的功能..而实现开闭原则的关键就是抽象化.
在"开-闭"原则中,不允许修改的是抽象的类或者接口,允许扩展的是具体的实现类,抽象类和接口在"开-闭"原则中扮演着极其重要的角色..即要预知可能变化的需求.又预见所有可能已知的扩展..所以在这里"抽象化"是关键!
当然对于修改,我们不可能完全避免,也不可能完全预知到未来的变化.所以我们要做到尽量去不要修改,或者少的修改就能达到我们的目标.
例如:对于简单工厂模式.我们有能力预知到未来可能添加计算,所以,我们将运算类抽象出来.为了以后方便扩展.这里的运算类是不可以修改的.但是对于他的子类.我们是可以扩展的.
设计模式中的体现UML图
二:依赖倒转原则
就是说要依赖抽象,而不要依赖具体的实现..如果说开闭原则是目标,依赖倒转原则是到达"开闭"原则的手段..如果要达到最好的"开闭"原则,就要尽量的遵守依赖倒转原则..可以说依赖倒转原则是对"抽象化"的最好规范!!
通俗的说就是只有抽象的东西才是最稳定的,也就是说,我们依赖的是它的稳定。如果将来“抽象”也不稳定了,那么谁稳定我跟谁,其实说白了不就是傍大款吗!
依赖倒转原则是达到开闭原则的途径。要做到依赖倒转原则,使用抽象方式耦合是关键。由于一个抽象耦合总要涉及具体类从抽象类继承,并且需要保证在任何引用到某类的地方都可以改换成其子类,因此,里氏代换原则是依赖倒转原则的基础,依赖倒转原则是 OOD 的核心原则,设计模式的研究和应用都是用它作为指导原则的
比如我们在观察者模式中(Observer)这里的通知者,就不应该是具体.因为我们应当考虑到如果前台那里换了人怎么办?这个通知还可以是其他人通知.比如老板要通知去做某件事怎么办?为了让大家都能用这个通知.所以要设置成抽象的.这里的前台,老板都要依赖这个通知.也就是说.细节要依赖抽象.
三:里氏代换原则:
定义:子类型必须能够替换它们的父类型[DH]
这个原则是对继承的一个约束,也就是说,继承中子类严格满足"is a "的关系.这里我个人有深刻的体会.尤其是在看别人的UML图的时候.
对你帮助很大.当你看到一个继承的时候.要习惯性的把他的父类和子类看成一个整体.这样会有助于你去理解各个类之间的关系.因为根据里氏代换原则.父类出现的地方子类也可以出现.
比如我们再看工厂模式的时候,你看到有的书上简单工厂类关联着运算父类.有的书上是关联着运算类的子类.其实仔细想想他们都没有错,
父类和子类的关联都是一样的,父类能出现的地方,子类就可以出现.
在设计模式中的体现:
设计模式中所有继承都能体现着这一原则.下边是一个不符合的例子
四:单一职能原则
定义:就一个类而言,应该仅有一个引起他变化的原因[DH]
也就是说,不要把变化原因各不相同的职责放在一起,因为不同的变化会影响到不相干的职责。再通俗一点地说就是,不该你管的事情你不要管,管好自己的事情就可以了,多管闲事害了自己也害了别人。(当然这里说的多管闲事跟见义勇为是两回事,我们提倡见义勇为!)
这个就是说,一个类尽量做到了功能单一,比如在mvc中,判断数据的类和添加数据库的类一定要分开.单一职能的不是说职能多了我们实现不了,是
为了后期的测试维护,每个类的很单一,我们找错误的时候就可以一步到位.添加新的功能的时候,也不用牵扯到很多的类.
在设计模式中的体现:
烤肉者就管烤肉,他也不管收钱,也不管记录.这样把"地摊"上的烤肉者分成服务员和烤肉的人.让职责单一.不容易出错.
上边的都是几个原则,下面介绍两个法则:
(1)迪米特法则:系统中的类,尽量不要与其他类互相作用,减少类之间的耦合度,因为在你的系统中,扩展的时候,你可能需要修改这些类,而类与类之间的关系,决定了修改的复杂度,相互作用越多,则修改难度就越大,反之,如果相互作用的越小,则修改起来的难度就越小..例如A类依赖B类,则B类依赖C类,当你在修改A类的时候,你要考虑B类是否会受到影响,而B类的影响是否又会影响到C类..如果此时C类再依赖D类的话,呵呵,我想这样的修改有的受了..
(2)接口隔离法则:这个法则与迪米特法则是相通的,迪米特法则是目的,而接口隔离法则是对迪米特法则的规范..为了做到尽可能小的耦合性,我们需要使用接口来规范类,用接口来约束类.要达到迪米特法则的要求,最好就是实现接口隔离法则,实现接口隔离法则,你也就满足了迪米特法则...这里也体现了一个依赖原则,要尽量依赖抽象,不要依赖具体.
掌握一定的面向对象设计原则才能掌握面向对象设计模式的精髓,从而实现灵活运用设计模式。
注:文章中部分理解参考于网络