论坛首页 Java企业应用论坛

单一职责

浏览 2599 次
锁定老帖子 主题:单一职责
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (4)
作者 正文
   发表时间:2010-05-29   最后修改:2010-05-31
OO
单一职责:一个类仅有一个引起它变化的原因,职责就是变化.
从两个角度来分析这条原则:职责,单一性.
A:先看一下现实世界中职责的描述: 职务上应尽的责任.
例如:工厂的职责就是生产产品,流水线上的工人的职责就是负责完成产品生产环节过程中的某一个环节,产品的职责就是负责将自身转化为money,现实世界是复杂的,工厂除了核心的生产职责外,还有其它角度的职责如:社会职责,原因在于,比如生产过程中废水,废气,噪声的污染影响到周围人的生活;工厂需要工人完成生产任务,它为社会提供就业机会,就担当了一份社会的责任,但像富士康这种工厂,它已经从生产型转变成杀手联盟了,这估计是企业转型最特殊的情况之一;三鹿,一个良好形象的企业也是转型失败,也是不好好搞生产,玩儿杀人游戏,杀的还是社会的未来,最后把自已也搞死了。
现实世界是复杂的,一个事物不但有主要职责,还有一系列次要职责,职责实际上是人们对一些行为的定义,并且要对这些行为进行分类,哪些是这个事物应该做的,哪些是不应该做的;对于一个事物,它的职责是会演变的,演变的分类可能是增加了一项新的职责,或者是将原有职责分解,划分出去以独立成新职责。演变的原因可能是内在的,也可能是外
在的,但根本原因是人对客观世界认知的程度,客观世界映射到人的主观世界,并进行整理分类,以更清晰的认知客观世界。
程序中的职责没有现实世界这么复杂,程序总是关注某一方面的问题. 
这里的不复杂并不意味着简单,它只是一种相对性,一个不恰当的量化: 在0到无穷大之间表示解决问题的能力同样也代表着问题的困难度,假定我的能力值为100,对现实世界的完整建模将需要无穷大的能力值,对一些程序的建模需要10000的能力值,当然也会有落到100以内的.10000相对于无穷大是简单的,但对于100,它们仍不是一个级别的. 
B:单一性:单一性并不是完全意义上的量化,它也是一种相对性,它的目的就是为了得到清晰性,准确性,简洁性。   
看一个实际的例子,Spring的BeanFactory结构: 一个BeanFactory的主要职责就是管理对象的生命周期.过程描述:先要得到材料数据BeanDefinition的对象,然后进行Bean对象的组装, 组装步骤在BeanFactory中完成, 但功能定义并不在BeanFactory中,交由BeanDefinitionReader,BeanWrapper完成, BeanDefinitionReader从文件中得到BeanDefinition然后由BeanDefinitionRegistry注册到BeanFactory,BeanFactory得到这些材料数据后就开始装配Bean,实际功能交由BeanWrapper完成.  BeanWrapper提供装配Bean的功能,给BeanWrapper提供原材料数据,就可以得到组装后的Bean对象.
与BeanFactory相关的其中有两个接口:BeanDefinitionRegistry,SingletonBeanRegistry.
首先看BeanDefinitionRegistry,它提供注册BeanDefinition的功能,它的职责很清晰,对它的使用有两种方式,第一种是组合的方式,别一种是继承方式,选择的标准是BeanFactory是否需要BeanDefinitionRegistry的中功能, 这要从两个角度看,配置方式与编程方式,如果BeanFactory不需要BeanDefinitionRegistry中定义的功能方法,对读取配置文件的方式影响不大,读取配置文件就像是一个后台进程,它的实现细节应该被隐藏掉,但组合方式将使BeanFactory丧失编程性的BeanDefinition注册功能,因为BeanFactory对外没有提供注册的功能. 此时应该使用继承方式,将功能暴露出来,然后再分类。其实这里的配置方式或编程方式的讨论对于生成的BeanDefinition没有任何影响.对于BeanFactory来说BeanDefinition是如何得到的并不重要,重要的是得到了BeanDefinition,那就要提供方法将得到的BeanDefinition注册进来.
BeanDefinitionRegistry的这个接口是从1.0就存在,但在1.0之前是什么样呢?是设计阶段就想到了这种分离呢,还是经历了重构,提炼超接口形成的呢?    
再来看SingletonBeanRegistry,它提供向BeanFactory注册singleton对象,从功能作用上来看与BeanDefinitionRegistry是相相似的,不同的是BeanDefinitionRegistry注册原材料携带者BeanDefinition,SingletonBeanRegistry注册已完成加工的成品Bean对象. SingletonBeanRegistry的接口是在2.0出现的,但它的核心方法registerSingleton(String,Object)是一直都存在的,这个是重构的结果,  SingletonBeanRegistry封装了演变后的职责。
总结:
      1.对于职责,重要的是分离功能的定义和功能的使用。封装就是用来封装这些功能定义的。
      2.单一性, 概念描述的准确最重要.  接口隔离原则是针对接口设计单一性的讨论.
     3.单一职责最重要的是给出了一个分类的标准,类之间的依赖组合关系的职责划分,继承体系结构中每一层次的职责划分.
     4.我们可以将单一职责这个定义应用到其它粒度模块上: 变量,方法,类,包,层次. a.比如对局部变量和方法参数不要二次赋值;b.方法的功能明确,方法的抽象级别应该是清晰的,这也是类设计的一部分. c.什么样的一组类应该组织成一个包,什么样的类不应该入这个包,这个是对一组类的分类. d. 层次, 确定那些层次,每一层次的职责是什么,一个实际的逻辑它应该属于划分好的哪个层次的职责.
     5.单一职责与封装.    单一职责是封装的标准,它指明什么应该封装,什么不应该封装,4里的就是在单一职责指导下的不同封装做法。  其中一个分离标准:分离不变部分与变化部分,对设计有指导性意义。
      6.单一职责要避免发散式与霰弹式变化,理想情况下形成一对一关系.

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics