Java设计模式中单一职责原则(SRP)介绍

2024-03-13 04:58

本文主要是介绍Java设计模式中单一职责原则(SRP)介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:http://blog.csdn.net/qq_24451605/article/details/51346786

单一职责原则(Single Responsibility Principle)

SRP 基本概念

单一职责原则

  • 定义:应该有且仅有一个原因引起类的变更,也就是接口或类和职责的关系是一一对应的。
  • 难点:职责的划分
    • 在不同情景和生产环境下我们对职责的细化是不同的(职责单一的相对性)
    • 单一职责原则提出的是一个评价接口是否优良的标准,但是职责和变化原因是不可度量的,因项目而异,因环境而异(不可度量性)
  • 优势: 
    • 类的复杂性降低:每个类或接口都只实现单一的职责,定义明确清晰
    • 可读性提高:定义明确清晰,自然带来较高的代码可读性
    • 可维护性提高:代码可读性强,更容易理解,自然方便维护,而且职责单一所以类之间耦合度较低,所以更容易修改。
    • 拓展性更好:有新的职责需要拓展,只需要继承对应的接口实现新的实现即可。

例讲SRP

因为面向对象的编程是推崇面向接口的编程的,我们对外暴露的方法也最好是以接口的形式定义,再由具体的类进行实现,诸多的好处就不再赘述,我们下面就基于一个简单的场景进行设计,体现单一职责的好处:

场景的定义

比如Pear是一家电子产品商,它要生产pad,phone,watch等设备,但是有一些重复的功能,如果分别设计一套,很显然并不划算,那么接口定义上我们就可以根据功能划分设定单一职责的接口:

接口的定义
//可以拨打电话
interface Callable{void call ();
}//可以触摸控制
interface Touchable{void touch();
}//可以消息提醒
interface MessagePromptable{void prompt();
}//可以接入键盘
interface KeyBoardMatchable{void match();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
实现接口的类依旧单一职责
class StandardCall implements Callable{@Overridepublic void call() {System.out.println("Call to somebody!");}
}class StandardTouch implements Touchable{@Overridepublic void touch() {System.out.println("touch to press the button!");}
}class StandardPromt implements MessagePromptable{@Overridepublic void prompt() {System.out.println(" someone contact to you,sir!");}
}class StandardMatch implements KeyBoardMatchable{@Overridepublic void match() {System.out.println("The keyBoard is ready to work!");}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
产品的生产
  • 我们如果基于我们现有的技术生产一部手机,那么我们需要它能打电话触屏控制消息提醒:
//在声明这台手机时我们就明确知道了它的功能
class MyPhone implements Callable,MessagePromptable,Touchable{//无需重复研发已有的技术,直接装载即可private Callable caller = new StandardCall();private MessagePromptable prompter = new StandardPromt();private Touchable toucher = new StandardTouch();@Overridepublic void call() {caller.call();}@Overridepublic void prompt() {prompter.prompt();}@Overridepublic void touch() {toucher.touch();}
}public class SRPTest {public static void main ( String [] args ){MyPhone phone = new MyPhone();phone.call();phone.prompt();phone.touch();}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 假如我们需要出一款新的手机,但是我们只是拥有了新的呼叫技术,那么只需要在实现这项技术时继承Callable接口,然后在之前手机的Callable的具体是凶案类换成新的技术即可,只需要修改一行代码,是不是感觉棒棒的。职责的单一,对于我们对于现有类的修改造成的影响有了约束
  • 那么如果我想生产一个Pad呢,同理啊,只需要在已有技术上装载即可啊,Pad类依旧只是单一的整合技术形成产品的职责,整合成产品研发出技术的职责分离,为我们的类的拓展带来了方便
class MyPad implements Touchable,KeyBoardMatchable{Touchable toucher = new StandardTouch();KeyBoardMatchable matcher = new StandardMatch();@Overridepublic void match() {toucher.touch();}@Overridepublic void touch() {matcher.match();}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

总结

通过上面额例子,可以有一个更清晰的理解,其实如果单个接口都提供一个实现类会导致类额数量很庞大,使用起来很不方便,所以我们可以整合一些功能。简而言之:

对于单一职责原则,接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化
  • 下面一个例子,我们的接口依旧单一职责,但是接听和拨打电话的功能往往是不可分的,他们会同时发生变化,所以我们可以提供一个同时继承两个接口的实现类。
class CallAndPrompt implements Callable,MessagePromptable{@Overridepublic void call() {System.out.println("Hello, I have some thing to tell you!");}@Overridepublic void prompt() {System.out.println("Hello,what do you want to tell me!");}
}//在声明这台手机时我们就明确知道了它的功能
class MyPhone implements Callable,MessagePromptable,Touchable{//无需重复研发已有的技术,直接装载即可private Callable caller = new CallAndPrompt();//不同的接口调用同一个实现类的不同功能private MessagePromptable prompter = (MessagePromptable)caller;private Touchable toucher = new StandardTouch();@Overridepublic void call() {caller.call();}@Overridepublic void prompt() {prompter.prompt();}@Overridepublic void touch() {toucher.touch();}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

从上面的例子,可能你会更理解我的总结。但是原则这个东西要遵守,但是没必要死守。在实际的设计中还是要学会变通。毕竟经典的设计模式也不总是遵守这些设计原则,但他们依旧被广泛地应用到实际当中,而且表现还不错


这篇关于Java设计模式中单一职责原则(SRP)介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803704

相关文章

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件

解决SpringBoot启动报错:Failed to load property source from location 'classpath:/application.yml'

《解决SpringBoot启动报错:Failedtoloadpropertysourcefromlocationclasspath:/application.yml问题》这篇文章主要介绍... 目录在启动SpringBoot项目时报如下错误原因可能是1.yml中语法错误2.yml文件格式是GBK总结在启动S

Spring中配置ContextLoaderListener方式

《Spring中配置ContextLoaderListener方式》:本文主要介绍Spring中配置ContextLoaderListener方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录Spring中配置ContextLoaderLishttp://www.chinasem.cntene

java实现延迟/超时/定时问题

《java实现延迟/超时/定时问题》:本文主要介绍java实现延迟/超时/定时问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java实现延迟/超时/定时java 每间隔5秒执行一次,一共执行5次然后结束scheduleAtFixedRate 和 schedu

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

idea maven编译报错Java heap space的解决方法

《ideamaven编译报错Javaheapspace的解决方法》这篇文章主要为大家详细介绍了ideamaven编译报错Javaheapspace的相关解决方法,文中的示例代码讲解详细,感兴趣的... 目录1.增加 Maven 编译的堆内存2. 增加 IntelliJ IDEA 的堆内存3. 优化 Mave

Java String字符串的常用使用方法

《JavaString字符串的常用使用方法》String是JDK提供的一个类,是引用类型,并不是基本的数据类型,String用于字符串操作,在之前学习c语言的时候,对于一些字符串,会初始化字符数组表... 目录一、什么是String二、如何定义一个String1. 用双引号定义2. 通过构造函数定义三、St

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码