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

单一职责原则

定义

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

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

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

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

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

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

好处

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

难点

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

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

妥协原则:

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

总结

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

范例

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

@Service
public class UserService {

    public void register(UserInfo info) {
    
    }

    public void login(LoginUser loginUser) {
    
    }
}

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

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

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值