基本介绍
对类来说,即一个类只负责一项职责。如类A负责两个不同的职责:职责一,这则二。当职责一需求变更而改变A时,可能造成职责2的执行错误,所以需要将类A的粒度分解为A1,A2
应用实例
方案一:
public class Application {public static void main(String[] args) {Vehicle vehicle = new Vehicle();vehicle.run("汽车");vehicle.run("轮船");vehicle.run("飞机");}}违反了单一职责原则:该类负责了三个职责,应该将其粒度分解class Vehicle {public void run(String vehicle){System.out.println(vehicle+" 在公路上运行。。。");}}
运行结果
汽车 在公路上运行。。。轮船 在公路上运行。。。飞机 在公路上运行。。。
方案二:
public class Application {public static void main(String[] args) {Vehicle vehicle = new Vehicle();vehicle.run("汽车");VehicleAir vehicleAir = new VehicleAir();vehicleAir.run("飞机");VehicleWater vehicleWater = new VehicleWater();vehicleWater.run("轮船");}}方案2 分析1:遵守了单一职责原则2:但是这样改动很大,即将类分解,同时也修改了客户端3:改进,当职责不是很多的情况下,可以将单一职责范围缩小到方法层次class Vehicle {public void run(String vehicle){System.out.println(vehicle+" 在公路上运行。。。");}}class VehicleAir {public void run(String vehicle){System.out.println(vehicle+" 在空中上运行。。。");}}class VehicleWater {public void run(String vehicle){System.out.println(vehicle+" 在水面上运行。。。");}}
运行结果:
"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汽车 在公路上运行。。。飞机 在空中上运行。。。轮船 在水面上运行。。。
方案三:
public class Application {public static void main(String[] args) {Vehicle vehicle = new Vehicle();vehicle.run("汽车");vehicle.runAir("飞机");vehicle.runWater("轮船");}}方案3分析1:这种修改方法没有对原由类做大的修改,只是增加方法2:这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然遵守单一职责class Vehicle {public void run(String vehicle){System.out.println(vehicle+" 在公路上运行。。。");}public void runAir(String vehicle){System.out.println(vehicle+" 在空中上运行。。。");}public void runWater(String vehicle){System.out.println(vehicle+" 在水面上运行。。。");}}
运行结果:
"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汽车 在公路上运行。。。飞机 在空中上运行。。。轮船 在水面上运行。。。
单一职责原则注意事项和细节
- 降低类的复杂度,一个类只负责一项职责
- 提高累的可读性,可维护性
- 降低变更引起的风险
- 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中的方法数量足够少,可以在方法级别保持单一职责原则。
