单一职责原则(SRP:Single responsibility principle)又称单一功能原则。它规定一个类应该只有一个发生变化的原因。
一、起因
编码中,需要创建一只小鸟,既能飞,用能走。
我写的时候,我会定义两个接口,IFly,IWalk,然后实现他们。
然后,外部模块需要用到我的“鸟”,进行操作。这个时候,有同事过来了,说“按照SRP,你这个鸟有问题”
难道我要提供两只鸟:一只FlyBird,一只WalkBird?
二、问题
“一个类应该只有一个发生变化的原因”
在《敏捷软件开发:原则、模式与实践》90页,清晰的写着“我们把两个职责都耦合进了ModemImplementation类中,这不是所希望的,但或许是必要的,常常由于一些和硬件或者操作系统的细节有关的原因,迫使我们这样去处理。我们可以把它看做一个有缺陷的类,所有的依赖关系都是从它出发,谁也不需要依赖它。除了Main以为,谁也不需要知道它的存在。因此我们已经把丑陋的部分隐藏起来。”
三、思考
比如当前外部有一个大的舞台场景,里面有“鸟”,“云”,“天空”,
伪代码:
class Scene{
bird:Brid;
cloud:Cloud;
sky:Sky;
}
按照 “标准srp”,我提供的是一个“飞,走,职责揉进bird”的类,是“丑陋的鸟”。
那怎样写出一只“不丑陋的鸟”呢?
答案是,没有这样的一只鸟。因为你的鸟需要“飞,走”。
在书中提到的“main”,是我们现在用到的场景么?个人觉得,不是!!!
“main”应该是指最外层的调用者,而不是中间层的调用者。最外层只能是 文档类(入口类)。
对于外界来说,我的鸟,能飞,能走,已经是一个独立的组件了,不能将两者分离。
如果我创建两只鸟,FlyB,WalkB,那么,这鸟如果再中间层被使用,每次都要在两只鸟中艰难选择。
当然,调用者想用 ISP,这个要看他的需求了。
四、结论
个人觉得,我最开始的设计没有问题。SRP对于最底层的组件,可以适用;但是对于中间各层的组件,就会出现结构过于分散,职责过于细致,适用过于繁杂。