只有一个原因引起类的变化
变化是由需求引起的
需求是客户提出的
客户只关注特性,或者职责
所以,归结为只有一个职责引起类的变化
所以,一个类只包含一个职责,且包含一个完整的职责。
当然,这是理想的状态,理想的状态都是纯粹的状态,表明的是选择而不是规则。
就职责来说,职责的定义本身就不是统一的,职责的粒度,在每个人看来也不一样。
1,一个类应该只包含单一的职责,并且该职责被完整地封装在这个类中。 -〉 想象类和职责是两个圆,这两个圆是统一的。
2,单一职责被完整地封装在一个类中-〉首先,职责不会分散在别的类和依赖中,表明类中元素是高内聚的。其次,类的职责被完整地封装了,对外界的依赖是低耦合的。
3,多个职责置于一个类中的问题就是,一个职责的修改可能影响别的职责的正常工作。
4,实例分析:
职责接口定义:代码一
interface IAnimal{ public void breathe(String animal); }
职责实现:代码二
class Animal implements IAnimal{ public void breathe(String animal){ System.out.println(animal+"呼吸空气"); } } public class Client{ public static void main(String[] args){ IAnimal animal = new Animal(); animal.breathe("牛"); animal.breathe("羊"); animal.breathe("猪"); } }
现在假设上线后,需求变更:需要支持鱼呼吸水的处理。
A,按照单一原则的设计,具象化两个类来承担不同职责。在类级别添加对新增职责的支持
代码三:
class Terrestrial implements IAnimal{ public void breathe(String animal){ System.out.println(animal+"呼吸空气"); } } class Aquatic implements IAnimal{ public void breathe(String animal){ System.out.println(animal+"呼吸水"); } } public class Client{ public static void main(String[] args){ IAnimal terrestrial = new Terrestrial(); terrestrial.breathe("牛"); terrestrial.breathe("羊"); terrestrial.breathe("猪"); IAnimal aquatic = new Aquatic(); aquatic.breathe("鱼"); } }
对比代码二和代码三,可以看到两个变化:
1〉新增了两个子类
2〉变更了客户端代码
B,在代码级别添加对新增职责的支持
代码四:
class Animal implements IAnimal{ public void breathe(String animal){ if("鱼".equals(animal)){ System.out.println(animal+"呼吸水"); }else{ System.out.println(animal+"呼吸空气"); } } } public class Client{ public static void main(String[] args){ IAnimal animal = new Animal(); animal.breathe("牛"); animal.breathe("羊"); animal.breathe("猪"); animal.breathe("鱼"); } }
对比代码四和代码二,变化仅仅在方法处理逻辑增加了对鱼的处理,但这里从代码级别违背了单一原则,新增的处理可能影响原有逻辑:比如出现 牛呼吸水
C,在方法级别添加对新增职责的支持
代码五:
class Animal implements IAnimal{ public void breathe(String animal){ System.out.println(animal+"呼吸空气"); } public void breathe2(String animal){ System.out.println(animal+"呼吸水"); } } public class Client{ public static void main(String[] args){ IAnimal animal = new Animal(); animal.breathe("牛"); animal.breathe("羊"); animal.breathe("猪"); animal.breathe2("鱼"); } }
对比代码五和代码二,可以看到两个变化:
1〉新增了处理鱼的职责的方法
2〉变更了客户端代码
D,在接口级别添加对新增职责的支持
这个也就是接口隔离原则
我们知道接口和抽象类的区别
抽象类表示血缘关系
接口表示功能
比如你是鸟
鸟是抽象的
不管你是不是折翼的天使
生生世世你都是鸟
你能飞
飞是功能
除了鸟
还有别的也能飞
比如风筝
比如
扯回来
说接口
说功能
接口的设计原则也要遵循单一职责
或者单一功能
或者接口隔离原则
因为如果一个接口涵盖的功能过多
比如有个接口
能飞也能游泳
那小狗继承了这个接口之后
你能理解它的心情吗
你说小狗,我给你的接口里除了游泳还有飞哦
但是
除了游泳
它实际不能飞
所以
你会看到它哀怨的眼神
所以呢
我们需要接口隔离
杜绝捆绑销售
参考: