设计模式之设计原则-单一职责原则

来源:互联网 发布:seo外包优化 编辑:程序博客网 时间:2024/04/28 12:06

前言

最近在网上看到一本书《设计模式之禅》,想想最近都没怎么好好学习,自己作为一个码农,心里很惭愧,失去了学习动力的码农怎么能叫做码农?所以边看书边学习,这几篇关于设计模式的博客算是对这本书的一个学习总结吧!

要学习设计模式,首先要过6个设计原则的大关,所谓先理论后实践,后面所谓23种设计模式只不过是对6种设计原则的实现,我们废话不多讲,直接上第一种原则-单一职责原则。

常规操作

单一职责原则的精华有两点,”单一”,”职责”,我们简单理解起来可以这么说:一个类只负责与其相关的操作,其他的都不管,是吧?听起来是这个意思,单一的概念也有了,职责的概念也有了,但是实际上这样理解对不对呢?

举个例子(不好意思,由于是一边看书一边现学的,直接照搬书上的例子,别介意啊)我们定义一个用户信息类,这个用户信息可以做蛮多操作,例如设置获取用户ID,设置获取用户密码,设置获取用户名,修改密码,删除用户等等,那我们可以设计出这样一个接口:
用户信息类图
这个接口太简单了,拿出来举例子是不是小看大家了……,但是这个接口有问题啊,啥问题呢?用户的属性和行为没有分开设计,前边6个方法,用于操作用户的属性,后面的方法,是用户这个接口可以操作的动作,我们叫做行为,比如用户会修改密码啊,删除用户啊等等,这些是涉及到业务操作的行为方法,不能和用户对象自身的属性方法混在一起,那么怎么办呢?拆分啊,拆分之后变成这个样子:
划分职责后的用户信息类
那接下来我们怎么使用这个UserInfo类呢?看代码:

IUserInfo userInfo = new UserInfo();//操作用户属性的时候呢,我们就使用IUserBo接口IUserBo userBo = (IUserBo)userInfo;userBo.setPassword("123456");//执行用户动作的时候,使用IUserBiz接口IUserBiz userBiz = (IUserBiz)userInfo;userBiz.deleteUser(userBo);

这样实现了之后,我们就把用户的操作用户属性的职责和执行用户行为的职责拆分开来,这里就体现了单一职责原则的概念的重点”职责划分”,我们把原来一个接口要承载两个职责的IUserInfo,划分成两个接口,每一个接口负责一个相应的职责。原来这么简单,我们在项目中根据业务范围做对应的拆解就可以了嘛,看起来没什么。
那我们就照抄一下书中的定义:单一接口原则要求有且仅有一个原因引起类的变更

进一步分析

我们看下一个例子:
电话类图
这个电话看起来蛮简单,莫不是又想让我做拆解,分配职责?怎么分啊,打电话,聊天,挂断,这是标准的业务操作啊,还用分吗?
但是体会一下刚才的定义,有且仅有一个原因引起类的变更,这个电话有几个原因会引起变更?打电话,聊天,挂断都会引起类变更,其中打电话和挂断会引起设备状态的变更,从待机状态转变为打电话状态,然后从打电话状态转变为待机,而聊天会引起数据的变更,你说一句我说一句,都是数据在两端传输。这样我们就发现类两个职责了,一个是负责状态改变的职责,一个是负责数据传输的职责,ok,老套路,开始拆分吧,定义两个接口,然后找个手机类一实现就O了:
拆分后的Phone
使用起来也是和上边的一样,要打电话就用IStateManager,要聊天就用IDataTransfer。
ok,同样抄一下书上的单一职责的优点:

  1. 降低类的复杂性,职责定义明确
  2. 提高了可读性和可维护性
  3. 变更引起的风险降低了,如果以后电话升级了,能发短信了,我们也只是在IDataTransfer中增加一个sendSMS方法,实现类只要实现了这个接口就能发短信了,对于IStateManager没有任何影响。

到这里我们似乎简单的摸到了门道,单一职责原则原来就是把职责划分好,然后分别定义相应的抽象就o了,你说对了,但是难就难在怎么划分职责,如果用别的理由,dial和chat也能划分到一个职责中,所以说这个职责划分没有定性,而且有些职责也不一定非要定义接口,直接实现更快更灵活。所以说这些东西都需要放到实际项目中去考虑,这也应了那句”名言”:不根据实际项目进行的架构设计都是耍流氓。

接口,实现类以及方法

因为我们说接口用来定义职责,而实现类则是多方面职责的的实现,所以一般一个接口定义一个职责,这就叫做”单一”,而实现类则会是多个职责的实现,比如男人就是一个多职责实现,有做父亲的职责,做儿子的职责,做丈夫的职责,等等。这就要看我们在实际项目中怎么去拆解划分了,但是还是要明白,这东西不能照本宣科生搬硬套,有些时候只用划分一个职责就可以的偏偏要拆分出多个,那就是扯淡了,增加了系统复杂性,实现的时候又需要将原来拆分开来的组合起来才能完成,你这么做让程序员知道了小心他杀了你,杀了你,了你,你。
单一职责原则不仅仅用于接口和实现类,也适用于方法,例如我们有一个方法是修改用户密码,有些人会这么写,而且还不在少数:
一个方法承担多个职责
到时候option传1就是修改用户名,传2就是修改密码,传3就是修改用户角色,不能不说这样写确实很省事儿,一个方法能干好几件事儿是不是很好哇,但是对于单一职责来说这样就大错特错,一个方法承担多个职责,那么这个方法的职责就混乱了,而且对于别人来说也很不友好,人家还要先揣摩你这个修改用户信息到底修改的是啥,还要去查文档看看想要修改密码要传什么给option,这多不好呀,干嘛不写成这样呢:
一个方法一个职责
说实话这样写浪费不了多少时间,而且不论自己用还是别人用都清晰明了,何乐而不为呢?

小结

其实单一职责原则的概念不难理解,难啃的是职责的划分和实现,我们只有在项目设计中多积累经验,才能做到精准的判断职责范围以及实现方式,我等还需要多多学习啊。

1 0
原创粉丝点击