设计模式原则之:单一职责原则SRP
Posted 初念初恋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式原则之:单一职责原则SRP相关的知识,希望对你有一定的参考价值。
人生没有白走的路,每一步都算数
前言
在面向对象的软件设计中,只有尽量降低各个模块之间的耦合度,才能提高代码的复用率,系统的可维护性、可扩展性才能提高。面向对象的软件设计中,有23种经典的设计模式,是一套前人代码设计经验的总结,如果把设计模式比作武功招式,那么设计原则就好比是内功心法。常用的设计原则有七个,本文将具体介绍单一职责原则。
设计原则简介
- 单一职责原则:专注降低类的复杂度,实现类要职责单一;
- 开放关闭原则:所有面向对象原则的核心,设计要对扩展开发,对修改关闭;
- 里式替换原则:实现开放关闭原则的重要方式之一,设计不要破坏继承关系;
- 依赖倒置原则:系统抽象化的具体实现,要求面向接口编程,是面向对象设计的主要实现机制之一;
- 接口隔离原则:要求接口的方法尽量少,接口尽量细化;
- 迪米特法则:降低系统的耦合度,使一个模块的修改尽量少的影响其他模块,扩展会相对容易;
- 组合复用原则:在软件设计中,尽量使用组合/聚合而不是继承达到代码复用的目的。
这些设计原则并不说我们一定要遵循他们来进行设计,而是根据我们的实际情况去怎么去选择使用他们,来让我们的程序做的更加的完善。
单一职责原则
就一个类而言,应该仅有一个引起它变化的原因,通俗的说,就是一个类只负责一项职责。此原则的核心就是解耦和增强内聚性。
如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计。
优点
:
(1)降低类的复杂度;
(2)提高类的可读性,提高系统的可维护性;
(3)降低变更引起的风险(降低对其他功能的影响)。
我们来举一些简单的例子来说明一下这个单一职责原则
public class Animal {
public void breathe(String animal) {
System.out.println(animal + "生活在陆地上");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
}
}
运行结果:
牛生活在陆地上
羊生活在陆地上
动物并不是都生活在陆地上的,鱼就是生活在水中的,修改时如果遵循单一职责原则,需要将Animal类细分为陆生动物类Land,水生动物Water,代码如下:
public class Land {
public void breathe(String animal) {
System.out.println(animal + "生活在陆地上");
}
}
public class Water {
public void breathe(String animal) {
System.out.println(animal + "生活在水里");
}
}
public class Test {
public static void main(String[] args) {
Land land = new Land();
land.breathe("牛");
land.breathe("马");
Water water = new Water();
water.breathe("鱼");
}
}
运行结果:
牛生活在陆地上
马生活在陆地上
鱼生活在水里
但是问题来了如果这样修改花销是很大的,除了将原来的类分解之外,还需要修改客户端。而直接修改类Animal来达成目的虽然违背了单一职责原则,但花销却小的多,代码如下:
public class Animal {
public void breathe(String animal) {
if ("鱼".equals(animal)) {
System.out.println(animal + "生活在水里");
}
System.out.println(animal + "生活在陆地上");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
animal.breathe("鱼");
}
}
运行结果:
牛生活在陆地上
马生活在陆地上
鱼生活在水里
可以看到,这种修改方式要简单的多。但是却存在着隐患:有一天需要将鱼分为生活在淡水中的鱼和生活在海水的鱼,则又需要修改Animal类的breathe方法,而对原有代码的修改会对调用“猪”“牛”“羊”等相关功能带来风险。
这种修改方式直接在代码级别上违背了单一职责原则,虽然修改起来最简单,但隐患却是最大的。还有一种修改方式:
public class Animal {
public void breathe(String animal) {
System.out.println(animal + "生活在陆地上");
}
public void breathe1(String animal) {
System.out.println(animal + "生活在水里");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
animal.breathe1("鱼");
}
}
运行结果:
牛生活在陆地上
马生活在陆地上
鱼生活在水里
可以看到,这种修改方式没有改动原来的方法,而是在类中新加了一个方法,这样虽然也违背了单一职责原则,但在方法级别上却是符合单一职责原则的,因为它并没有动原来方法的代码。
总结
以上通过一个应用场景简单介绍了下单一职责原则的使用,上面三种设计,没有最合理,只有最合适。
这三种方式各有优缺点,那么在实际编程中,采用哪一中呢?其实这真的比较难说,需要根据实际情况来确定。
例如本文所举的这个例子,它太简单了,它只有一个方法,所以,无论是在代码级别上违反单一职责原则,还是在方法级别上违反,都不会造成太大的影响。 实际应用中的类都要复杂的多,一旦发生职责扩散而需要修改类时,除非这个类本身非常简单,否则还是遵循单一职责原则的好。
理解单一职责原则,最重要的就是理解职责的划分,职责划分的粒度取决于需求的粒度。
以上是关于设计模式原则之:单一职责原则SRP的主要内容,如果未能解决你的问题,请参考以下文章