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层负责页面请求转发相关职责

相关推荐
shuangrenlong6 分钟前
slice介绍slice查看器
java·ubuntu
牧竹子7 分钟前
对原jar包解压后修改原class文件后重新打包为jar
java·jar
数据小爬虫@17 分钟前
如何利用java爬虫获得淘宝商品评论
java·开发语言·爬虫
喜欢猪猪19 分钟前
面试题---深入源码理解MQ长轮询优化机制
java
草莓base1 小时前
【手写一个spring】spring源码的简单实现--bean对象的创建
java·spring·rpc
drebander1 小时前
使用 Java Stream 优雅实现List 转化为Map<key,Map<key,value>>
java·python·list
乌啼霜满天2491 小时前
Spring 与 Spring MVC 与 Spring Boot三者之间的区别与联系
java·spring boot·spring·mvc
tangliang_cn1 小时前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟1 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
Grey_fantasy2 小时前
高级编程之结构化代码
java·spring boot·spring cloud