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 小时前
医院陪诊管理系统怎么选择?——2026 年选型避坑与架构参考
java·开发语言·陪诊系统·陪诊app·医院陪诊陪护
CodeStats1 小时前
【Spring事务】Spring事务注解 @Transactional 完整体系:从 MySQL 隔离级别到 MyBatis 原理详解
java·spring·mybatis·事务·transactional
我命由我123452 小时前
Android 开发问题:为 PDFView 设置一个带有黑色边框的背景 drawable,但边框没有生效
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
都叫我大帅哥4 小时前
从Python到Java:为什么企业级Agent最终会选择Java?
java·ai编程
wanderist.4 小时前
Lambda表达式在算法竞赛中的应用
java·开发语言·算法
腻害兔5 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:IM 即时通讯模块,一个被低估的「全功能聊天系统」
java·前端·vue.js·产品经理·ai编程
心念枕惊6 小时前
.NET CORE 授权进阶-角色、策略与动态权限实现
java·前端·.netcore
景同学7 小时前
把 AI 用到线上运维:可行、有效,前提是喂足信息——一次 Full GC 排障实录
java·人工智能·后端
C++、Java和Python的菜鸟8 小时前
第7章 后端Web实战(Tlias系统)
java
憧憬成为java架构高手的小白8 小时前
黑马八股--spring框架学习
java·学习·spring