设计模式中的很多思想还是很有意思的,刚毕业的时候接触设计模式感觉有点高深,坐而论道,感觉还是有些虚,平时做的小练习还能自己捣鼓一番,自己使用一下设计模式,然后大刀阔斧的改动代码,随心所欲,写完以后还能热乎劲上来高兴几天,时间长了就忘了很多的东西,只是感觉设计模式就是抽象,自己感觉也抽象。如果死磕着问自己,估计大脑里还是没什么印象了。到了工作中,又发现有些功能或者思想固然好,但是要在已有的项目中做一些改动,一下子又有点不知所措,时间长了,思想和行动就脱节了。工作中以面向对象为目标,实际中做着结构化的思路开发。 设计模式的这几个原则自己是看了忘,忘了以后时间长了也忘了看了。如此恶性循环。 看别人总结的原则描述很是详尽,但是看代码还是不够通俗,自己也来捣鼓一下,从自己的思路和理解来总结总结设计模式和工作生活的联系。
单一职责原则(Single Responsibility Principle)
定义:不要存在多于一个导致类变更的原因。即一个类只负责一项职责。
在系统中发生各种各样的问题是很常见的,可能对于一些比较紧急的问题,就需要提供补丁了,但是补丁可以解决问题,如果是高手就从根本上分析问题,找到问题的根源,从源头上解决,当然这种改动可能涉及的改动范围比较大,对于紧急补丁而言是不现实的,那么就头痛医头,脚疼医脚,先做一些不是很规范严谨的改动。等补丁上去了,之后各种各样的原因,变更就这么遗留下来了。等到之后的人来看的时候,又会抱怨代码写的太差,太不规范了,但是让他改,他还是没底,于是乎这种“懒惰”的保守思想保留了下来,直到第20个人进入了项目,发现一个方法几百几千个if-else,代码都不知道改从何该起。。。 这个也就说明了对于系统中出现的复杂校验,可以尽可能的提前做优化改进,保证功能的完整和单一,随着系统规模变大,模糊,不稳定的校验就会导致系统更严重的问题。
里氏替换原则(Liskov Substitution Principle)
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
解决方案:当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
可口可乐在全球都奉行着统一的标准,使得在任何地方口味都基本一致。我们可以理解可口可乐的产品秘方是一个类,全球的可口可乐都给予它来作为生产的标准,用软件设计的角度来说,全球各地的可口可乐公司都是基于父类的产品标准,没有对可口可乐的口味有任何改动,如果基于不同的口味,可以根据情况定制,但经典的口味还是保留不变。
说了可口可乐,来举个反例,比如说市面上苹果手机很畅销,国内的一些公司就开始复制了苹果的外观和基本的界面效果,有了所谓的High phone,但是苹果的核心的用户体验和产品性能这些特性厂商也没办法继承复制下来,因为苹果公司不可能给它这些东西。那他就自己来做,最后只要看起来界面主题和外观和苹果手机差不多就行了。从软件设计的角度来说,山寨产品继承了苹果手机的一些特性,但是有些核心特性没有的时候,子类就重写了父类的方法,这样使用效果和感官也大打折扣。
同样次品,劣品的道理也是类似,我就不多说了,你懂的。
依赖倒置原则(Dependence Inversion Principle)
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。
大家这些年买火车票比以前方便多了,以前基本都是通过车站的窗口或者黄牛来买,后来有了一些代理,买票就不用跑那么远了,前几年,铁道部开放了网上购买车票的方式,买票更方便了,现在还可以电话订票,通过其他的网站代理来买票。可以说买票的途径有很多种。可以理解买票时一个抽象的行为,我们只依赖于抽象,保证能买到票就行,至于通过哪种渠道,根据大家自己的情况。这样我们买票就依赖于抽象不依赖于具体的实体了。
在工作中,邮件组还是很有工作效率的,比如公司有一个技术支持部门,设定为一个邮件组,在部门内部做了邮件的各种转发策略,保证华北区的客户问题发送到指定的人的邮箱中,如果支持的人有多个,那就都发送给他们,现在客户有一个问题,他就直接发送给这个技术支持的邮件组。他无须知道具体要发送给哪一个人,只要这个问题能够得到反馈和解释就可以了。这就是依赖倒置所要表达的中心思想。
接口隔离原则(Interface Segregation Principle)
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
迪米特法则(Law Of Demeter)
定义:一个对象应该对其他对象保持最少的了解。
解决方案:尽量降低类与类之间的耦合。
工作中我们经常要汇报工作的情况,但是从领导的角度而言,他更关心结果,不是过程,所以你在汇报工作的时候涉及太多的细节,会把自己引入一个无形的漩涡中,比如报告中提到了一个细节,和a部门同事a有什么关系,然后领到问你同事a的情况,问这个问题,然后又牵扯出部门b的另一个同事,这样解释了半天,发现还把领导弄糊涂了。迪米特法则就是最少知道原则,只要言简意赅的说明,那些实现细节等等就不需要过多的牵扯了。
在微信的朋友圈中,如果你有好友a,b,c,但是好友a,b却互相不认识,那么你发的一些状态图片等,他们都能看到,他们给你回复的时候,朋友a看不到朋友b的留言,从根本上保证了用户的隐私,这也是微信中和微博中的一个不同点。微信的朋友圈更侧重个人的一些信息,不会暴露过多的信息。
开闭原则(Open Close Principle)
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
如果大家用Oracle数据库,就会发现oracle已经在很早的版本中使用了long的数据类型,但是使用中碰到了一些问题,发现没有预想的那么好,于是产生了lob的数据类型,但是oracle的产品已经提供了很多完善的功能,为了后续的支持,不能把这部分变更彻底去掉,彻底去掉就不兼容低版本了。所以在后续的版本中明确提出舍弃了long类型,更是在一些操作中限制了它的使用,但是还是没有从根本上把它去除,开闭原则在这里就是oracle为了支持低版本的功能,对于扩展开放,引入了新的数据类型,但是对修改关闭,不能彻底的改动long类型。
从这个角度最后来提一句,对于领土问题也是如此,对于扩展开放,如果能够摆正态度,有一个能够正常谈判的氛围,那么对于扩展是开放的,但是单方面的修改肯定是关闭的。