00.设计原则之单一职责原则

单一职责原则

定义

css 复制代码
A class should never have more than one reason to change.有且仅有一个原因引起类变更

职责:业务逻辑或者对象能够承担的责任,并以某种行为方式来执行

该原则提出了对对象的一种理想期望,对象不应该承担太多的职责,正如人不应该一心二用。唯有专注,才能保证对象的高内聚 唯有单一,才能保证对象的细粒度。 对象的高内聚和细粒度有利于对象的复用

从系统扩展性来说,单一职责原则还有利于对象的稳定,所谓职责,就是对象能够承担的责任,并以某种行为方式来执行。对象的职责总是要提供 给其他对象调用,从而形成对象与对象的协作,由此产生对象之间的依赖关系。对象的职责越少,则对象之间的依赖关系就越少,耦合度减弱,受 其他对象的约束与牵制就越少,从而保证系统的扩展性。

比如,在媒体播放器中,可以在MediaPlayer类中定义一组与媒体播放相关的方法,如 open(),play(),stop()等。这些方法从职责的角度来讲, 是内聚的,完全符合单一职责原则,专注与做一件事的要求。如果需求发生扩充,需要我们提供上传、下载媒体文件的功能。那么在设计时,就应 该定义一个新类如MediaTranser,由它来承担这一职责;而不是为了方便,草率地将其加入到MediaPlayer类中。

单一职责适用于接口、类、同时也适用于方法。方法的粒度也不宜过粗。

好处

类的复杂性降低,实现什么职责都有明确的定义 可读性提高,复杂性降低。 可维护性提高 变更引起的风险降低,变更是必不可少的 接口的单一职责做的很好的话,一个接口修改只对相应的实现类有影响,与其他接口无关。

难点

职责的划分无量化标准,这个需要根据项目的实际需求来判定。

实践建议: 接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化

妥协原则:

  1. 只要逻辑简单,才可以在代码级别上违背单一职责原则
  2. 只有类中方法数量足够少,才可以在方法级别上违背单一职责原则
  3. 实际项目中的类都要复杂的多,一旦发生职责扩散而需要修改类时,除非这个类本身非常简单,否则还要遵循单一职责原则

总结

  1. 如何理解单一职责原则 一个类只负责完成一个职责或者功能。不要设计大而全的类,要设计粒度小,功能单一的类。单一职责原则是为了实现代码高内聚、低耦合,提高 代码的复用性、可读性、可维护性
  2. 如何评判类的职责是否足够单一 不同的应用场景、不同阶段的需求背景、不同的业务层面,对同一个类的职责是否单一,可能会有不同的判定结果。实际上,一些侧面的判断指标 更具有指导意义和可执行性,比如下面的这些情况有可能说明类设计的不满足单一职责原则 ①类中的代码行数、函数、或者属性过多 ②类依赖的其他类过多,或者依赖类的其他类过多 ③私有方法过多 ④比较难给类起一个名字 ⑤类中大量的方法都是集中操作类中的某几个属性
  3. 类的职责是否设计得越单一越好 单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时类职责单一,类依赖的和被依赖的其他类也会 变少,减少了代码的耦合性,依此来实现代码的高内聚、低耦合。但是拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。

范例

我们以一个简单的用户登录和用户注册需求为例,用粗粒度的"用户操作"职责进行划分,我们很容易写出下面的代码

java 复制代码
@Service
public class UserService {

    public void register(UserInfo info) {
    
    }

    public void login(LoginUser loginUser) {
    
    }
}

UserService类完全遵循了单一职责原则,不管是register方法还是login方法都属于用户操作相关的职责。 如果客户提出登录需要满足多种第三方账号授权登录,注册功能需要支持短信,邮箱等校验,我们可能就要考虑将登录功能和注册功能以更加细粒度 的职责进行划分。如下代码

java 复制代码
@Service
public class LoginService {
    public void defaultLogin() {
        
    }   
    
    public void thirdLogin() {
        
    }
}

@Service
public class RegisterService {
    public void register() {
        
    }
    public boolean messageValidate() {
        
    }
    
    public boolean emailValidate() {
        
    }
}

随着业务的复杂度越来越高,每一个细粒度的职责都可能拥有非常复杂的逻辑,那么我们就要考虑按照项目需求进行更加细粒度的职责拆分,从而 保证单一职责原则下的低耦合度。

通过本范例,也印证了单一职责的原则划分无量化标准,每个开发者都有自己的考量角度和划分方式,一切都应该以项目实际需求进行设计。

讨论

单一职责原则,除了应用到类接口或者方法上,还能延伸到哪些其他的设计方面?

讨论1.分层架构模式 分层架构模式实际上也体现了单一职责原则,它将整个系统按照职责的内聚性分为不同的层。如MVC模式,M层负责数据相关的职责、V层负责页面 渲染相关的职责、C层负责页面请求转发相关职责

相关推荐
爆爆凯1 小时前
MobaXterm_Portable_v23.2 免费下载与使用教程(附安卓替代方案)
java·github
+7202 小时前
如何在java中用httpclient实现rpc get请求
java·qt·rpc
秋野酱2 小时前
基于 JavaWeb 的 SSM+Maven 微信小程序快递柜管理系统设计和实现(源码+文档+部署讲解)
java·微信小程序·maven·课程设计
你在我身后2 小时前
Spring-JAVA
java·后端·spring
卓越软件开发3 小时前
Java计算机毕业设计基于SSM宠物美容信息管理系统数据库源代码+LW文档+开题报告+答辩稿+部署教程+代码讲解
java·课程设计·宠物
丁总学Java3 小时前
Cannot deserialize instance of java.lang.String out of START_ARRAY token
java·windows·python
+7203 小时前
Java 的 HttpClient 中使用 POST 请求传递参数
java·开发语言
lozhyf4 小时前
如何使用Spring boot框架实现图书管理系统
java·spring
WalkingWithTheWind~4 小时前
Linux搭建Nginx直播流媒体服务RTMP/RTSP转Http-flv视频浏览器在线播放/Vue/Java/ffmpeg
java·linux·nginx·ffmpeg·vue·http-flv·rtsp