基本介绍

对类来说,即一个类只负责一项职责。如类A负责两个不同的职责:职责一,这则二。当职责一需求变更而改变A时,可能造成职责2的执行错误,所以需要将类A的粒度分解为A1,A2

应用实例

以交通工具案例讲解分析

方案一:

  1. public class Application {
  2. public static void main(String[] args) {
  3. Vehicle vehicle = new Vehicle();
  4. vehicle.run("汽车");
  5. vehicle.run("轮船");
  6. vehicle.run("飞机");
  7. }
  8. }
  9. 违反了单一职责原则:该类负责了三个职责,应该将其粒度分解
  10. class Vehicle {
  11. public void run(String vehicle){
  12. System.out.println(vehicle+" 在公路上运行。。。");
  13. }
  14. }

运行结果

  1. 汽车 在公路上运行。。。
  2. 轮船 在公路上运行。。。
  3. 飞机 在公路上运行。。。

方案二:

  1. public class Application {
  2. public static void main(String[] args) {
  3. Vehicle vehicle = new Vehicle();
  4. vehicle.run("汽车");
  5. VehicleAir vehicleAir = new VehicleAir();
  6. vehicleAir.run("飞机");
  7. VehicleWater vehicleWater = new VehicleWater();
  8. vehicleWater.run("轮船");
  9. }
  10. }
  11. 方案2 分析
  12. 1:遵守了单一职责原则
  13. 2:但是这样改动很大,即将类分解,同时也修改了客户端
  14. 3:改进,当职责不是很多的情况下,可以将单一职责范围缩小到方法层次
  15. class Vehicle {
  16. public void run(String vehicle){
  17. System.out.println(vehicle+" 在公路上运行。。。");
  18. }
  19. }
  20. class VehicleAir {
  21. public void run(String vehicle){
  22. System.out.println(vehicle+" 在空中上运行。。。");
  23. }
  24. }
  25. class VehicleWater {
  26. public void run(String vehicle){
  27. System.out.println(vehicle+" 在水面上运行。。。");
  28. }
  29. }

运行结果:

  1. "F:\Program Files\Java\jdk1.8.0_201\bin\java.exe" "-javaagent:F:\Program Files\JetBrains\IntelliJ IDEA 2018.3\lib\idea_rt.jar=65400:F:\Program Files\JetBrains\IntelliJ IDEA 2018.3\bin" -Dfile.encoding=UTF-8 -classpath "F:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\deploy.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\javaws.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jfxswt.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\management-agent.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\plugin.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar;E:\study\study_jvm\target\classes;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-web\2.4.1\spring-boot-starter-web-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter\2.4.1\spring-boot-starter-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot\2.4.1\spring-boot-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-autoconfigure\2.4.1\spring-boot-autoconfigure-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-logging\2.4.1\spring-boot-starter-logging-2.4.1.jar;F:\JAVA\Maven\Repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;F:\JAVA\Maven\Repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;F:\JAVA\Maven\Repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;F:\JAVA\Maven\Repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;F:\JAVA\Maven\Repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;F:\JAVA\Maven\Repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;F:\JAVA\Maven\Repository\org\yaml\snakeyaml\1.27\snakeyaml-1.27.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-json\2.4.1\spring-boot-starter-json-2.4.1.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\core\jackson-databind\2.11.3\jackson-databind-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\core\jackson-annotations\2.11.3\jackson-annotations-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\core\jackson-core\2.11.3\jackson-core-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.3\jackson-datatype-jdk8-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.3\jackson-datatype-jsr310-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.3\jackson-module-parameter-names-2.11.3.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-tomcat\2.4.1\spring-boot-starter-tomcat-2.4.1.jar;F:\JAVA\Maven\Repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.41\tomcat-embed-core-9.0.41.jar;F:\JAVA\Maven\Repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;F:\JAVA\Maven\Repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.41\tomcat-embed-websocket-9.0.41.jar;F:\JAVA\Maven\Repository\org\springframework\spring-web\5.3.2\spring-web-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-beans\5.3.2\spring-beans-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-webmvc\5.3.2\spring-webmvc-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-aop\5.3.2\spring-aop-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-context\5.3.2\spring-context-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-expression\5.3.2\spring-expression-5.3.2.jar;F:\JAVA\Maven\Repository\org\projectlombok\lombok\1.18.16\lombok-1.18.16.jar;F:\JAVA\Maven\Repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;F:\JAVA\Maven\Repository\org\springframework\spring-core\5.3.2\spring-core-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-jcl\5.3.2\spring-jcl-5.3.2.jar" design.Application
  2. 汽车 在公路上运行。。。
  3. 飞机 在空中上运行。。。
  4. 轮船 在水面上运行。。。

方案三:

  1. public class Application {
  2. public static void main(String[] args) {
  3. Vehicle vehicle = new Vehicle();
  4. vehicle.run("汽车");
  5. vehicle.runAir("飞机");
  6. vehicle.runWater("轮船");
  7. }
  8. }
  9. 方案3分析
  10. 1:这种修改方法没有对原由类做大的修改,只是增加方法
  11. 2:这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然遵守单一职责
  12. class Vehicle {
  13. public void run(String vehicle){
  14. System.out.println(vehicle+" 在公路上运行。。。");
  15. }
  16. public void runAir(String vehicle){
  17. System.out.println(vehicle+" 在空中上运行。。。");
  18. }
  19. public void runWater(String vehicle){
  20. System.out.println(vehicle+" 在水面上运行。。。");
  21. }
  22. }

运行结果:

  1. "F:\Program Files\Java\jdk1.8.0_201\bin\java.exe" "-javaagent:F:\Program Files\JetBrains\IntelliJ IDEA 2018.3\lib\idea_rt.jar=65400:F:\Program Files\JetBrains\IntelliJ IDEA 2018.3\bin" -Dfile.encoding=UTF-8 -classpath "F:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\deploy.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\javaws.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jfxswt.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\management-agent.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\plugin.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar;F:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar;E:\study\study_jvm\target\classes;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-web\2.4.1\spring-boot-starter-web-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter\2.4.1\spring-boot-starter-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot\2.4.1\spring-boot-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-autoconfigure\2.4.1\spring-boot-autoconfigure-2.4.1.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-logging\2.4.1\spring-boot-starter-logging-2.4.1.jar;F:\JAVA\Maven\Repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;F:\JAVA\Maven\Repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;F:\JAVA\Maven\Repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;F:\JAVA\Maven\Repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;F:\JAVA\Maven\Repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;F:\JAVA\Maven\Repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;F:\JAVA\Maven\Repository\org\yaml\snakeyaml\1.27\snakeyaml-1.27.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-json\2.4.1\spring-boot-starter-json-2.4.1.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\core\jackson-databind\2.11.3\jackson-databind-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\core\jackson-annotations\2.11.3\jackson-annotations-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\core\jackson-core\2.11.3\jackson-core-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.3\jackson-datatype-jdk8-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.3\jackson-datatype-jsr310-2.11.3.jar;F:\JAVA\Maven\Repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.3\jackson-module-parameter-names-2.11.3.jar;F:\JAVA\Maven\Repository\org\springframework\boot\spring-boot-starter-tomcat\2.4.1\spring-boot-starter-tomcat-2.4.1.jar;F:\JAVA\Maven\Repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.41\tomcat-embed-core-9.0.41.jar;F:\JAVA\Maven\Repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;F:\JAVA\Maven\Repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.41\tomcat-embed-websocket-9.0.41.jar;F:\JAVA\Maven\Repository\org\springframework\spring-web\5.3.2\spring-web-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-beans\5.3.2\spring-beans-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-webmvc\5.3.2\spring-webmvc-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-aop\5.3.2\spring-aop-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-context\5.3.2\spring-context-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-expression\5.3.2\spring-expression-5.3.2.jar;F:\JAVA\Maven\Repository\org\projectlombok\lombok\1.18.16\lombok-1.18.16.jar;F:\JAVA\Maven\Repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;F:\JAVA\Maven\Repository\org\springframework\spring-core\5.3.2\spring-core-5.3.2.jar;F:\JAVA\Maven\Repository\org\springframework\spring-jcl\5.3.2\spring-jcl-5.3.2.jar" design.Application
  2. 汽车 在公路上运行。。。
  3. 飞机 在空中上运行。。。
  4. 轮船 在水面上运行。。。

单一职责原则注意事项和细节

  1. 降低类的复杂度,一个类只负责一项职责
  2. 提高累的可读性,可维护性
  3. 降低变更引起的风险
  4. 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中的方法数量足够少,可以在方法级别保持单一职责原则。