面向对象设计原则之单一职责原则

  单一职责原则(Single Responsibility Principle,SRP)定义:一个对象应该只包含单一的职责,并且该终止被完整地封装在一个类中。通俗的说法就是一个类只包含一个使得她变法的原因。
  问题由来:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。

  解决方案:遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。
  
  例:
  只要做过项目,肯定要接触到用户、机构、角色管理这些模块,基本上使用的都是RBAC模型,确实是很好的一个解决办法。我们今天要讲的是用户管理、修改用户的信息、增加机构(一个人属于多个机构)、增加角色等,用户有这么的信息和行为要维护,我们就把这些写到一个接口中,都是用户管理类嘛,我们先来看它的类图,如图所示。

图1-1 用户信息维护类图

  太Easy的类图了,我相信,即使是一个初级的程序员也可以看出这个接口设计得有问题,用户的属性(Property)和用户的行为(Behavior)没有分开,这是一个严重的错误!非常正确,这个接口确实设计得一团糟,应该把用户的信息抽取成一个BO(Bussiness Object,业务对象),把行为抽取成一个BIZ(Business Logic,业务逻辑),按照这个思路对类图进行修正,如图所示。

图1-2 职责划分后的类图

  重新拆封成两个接口,IUserBO负责用户的属性,简单地说,IUserBO的职责就是收集和反馈用户的属性信息;IUserBiz负责用户的行为,完成用户信息的维护和变更。各位可能要说了,这个与我实际工作中用到的User类还是有差别的呀!别着急,我们先来看一看分拆成两个接口怎么使用。OK,我们现在是面向接口编程,所以产生了这个UserInfo对象之后,当然可以把它当IUserBO接口使用。当然,也可以当IUserBiz接口使用,这要看你在什么地方使用了。要获得用户信息,就当是IUserBO的实现类;要是希望维护用户的信息,就把它当作IUserBiz的实现类就成了,如代码清单所示。

代码清单 分清职责后的代码示例


IUserBiz userInfo = new UserInfo();

//我要赋值了,我就认为它是一个纯粹的BO

IUserBO userBO = (IUserBO)userInfo;

userBO.setPassword("abc");

//我要执行动作了,我就认为是一个业务逻辑类

IUserBiz userBiz = (IUserBiz)userInfo;

userBiz.deleteUser();

  问题解决了,但是我们来回想一下我们刚才的动作,为什么要把一个接口拆分成两个呢?其实,在实际的使用中,我们更倾向于使用两个不同的类或接口:一个是IUserBO, 一个是IUserBiz,类图应该如图所示
  这里写图片描述
  单一职责原则的难点是在于职责范围的认定。关于职责的认定是一个仁者见仁智者见智的话题,在实际开发中也会引起程序员之间的争论。有的人认为这些功能方法的实现目的很相似,必须要放在一个类中,有的人认为方法差别很大,必须要分拆成多个类,在多个类里面来实现。

  还有职责的扩散问题。软件一开发完上线后并不是一成不变的,随着社会的进步,需求的变更,软件的功能可能要做些维护更改,有时候会遇到职责扩散。所谓的职责扩散就是因为某种原因,职责R被分化为粒度更细的R1和R2。

  比如类C只负责一个职责R,这是符合单一职责原则的。但是后来需要把职责R拆分为职责R1和职责R2,那么这时候是否需要死守着单一职责原则,把类C也拆开为C1和C2。接着如果R1又需要细化为R11和R12呢……

  我们必须要意识到,一味的遵守单一职责原则,不停的分拆类所付出的开销是很大的。这时候就涉及到平衡的问题,平衡单一职责原则与修改造成的开销。我的观点是如果一个方法逻辑不复杂的情况下,可以修改方法实现,否则要拆分为两个方法,遵循方法级别的单一职责原则;如果一个类方法不多的情况下,可以只增加方法,而不用分拆为多个类,否则要拆分为多个类,遵循类级别的单一职责原则。

  遵循单一职责原则的优点:
    降低了类的复杂度。一个类只负责一项职责比负责多项职责要简单得多。
    提高了代码的可读性。一个类简单了,可读性自然就提高了。
    提高了系统的可维护性。代码的可读性高了,并且修改一项职责对其他职责影响降低了,可维护性自然就提高了。
    变更引起的风险变低了。单一职责最大的优点就是修改一个功能,对其他功能的影响显著降低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值