携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
简介
作为设计模式设计原则的第一个原则,单一职责原则可能99%的开发人员都知道这个理论和设计原则。但是往往在开发一个功能的过程中,由于各种各样的原因,大家还是在某些地方忽略了遵守单一职责原则,要么是为了快速完成功能,要么是一开始没想到后续还可以在这里还会有不同的逻辑,所以当第二个人第三个人接手这份代码的时候,就很可能出现修改了一个功能导致其他的功能发生故障。所以我们在工作中一定要将此原则铭记于心。 单一职责就是说,一个模块、一个类、一个方法不能太重,不能承担太多工作,否则这些功能就会耦合在一起,一旦一个功能发生改变就很可能会影响其他职责,所以我们将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中。它需要设计人员发现类的不同职责并将其进行分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关的实践经验。
应用
案例一:
我们在做接口时候通常会给移动端提供一个接口给后管提供一个接口。比如查询订单后台管理需要查询全部用户的订单列表,而用户移动端则需要查询自己的登录列表。其实这2个接口都是查询订单,要拿的数据也基本都是从订单表从获取的,所以为了统一或者方便简单,就将这2个功能设计成从一个接口获取。如下: 业务层接口:
public interface IOrderService {
Page<Order> getFrontOrderPageList(OrderRequest orderRequest);
}
业务层实现:
@Service
public class OrderService extends BaseService<Order, OrderMapper> implements IOrderService {
@Override
public Page<Order> getFrontOrderPageList(OrderRequest orderRequest) {
..//TODO
return null;
}
}
殊不知,这样给后续的开发和维护带来了很大的麻烦
- 大部分情况下前端所需要的字段是相对比较少的,客户只关注部分核心数据;而后台管理要查询的数据则是相对比较多的。所以这个时候要统一接口,就需要返回给前端很多冗余的数据。给网络和查询造成开销;而且安全性相对降低。
- 后续如果两边要查询逻辑变了,比如后台管理的查询要多关联几个表,又比如要给用户敏感信息进行脱敏,这个时候就要根据不同端的请求来做if/else了,这里又复杂了。
- 前后端权限不同,这里公用接口不好鉴权。
- .....还有不少缺点,想到再补充
案例二:
public void judgeOrder(Order order) {
if (Objects.equals(1, order.getOrderStatus())) {
sendPackage(order);//发货
sendMsg("已发货");
}else if(Objects.equals(2, order.getOrderStatus())) {
refund(order);//退款
sendMsg("退款");
}else if(Objects.equals(3, order.getOrderStatus())) {
change(order);//换货
sendMsg("换货");
}
}
那这段代码if/else逻辑全写在一个方法了,不符合高内聚原则,所以我们需要讲订单的各种处理进行拆分和封装。 定义一个处理订单的接口
public interface handerOrder {
//处理订单
void handle(Order order);
//发送消息
void sendMsg();
}
给各个订单状态定义处理类
public class SendPackageHander {
void handle(Order order) {
//发货
}
void sendMsg() {
//发送发货短信
}
}
同理给其他状态的订单处理也定义相应的实现类即可,如此则实现了单一职责原则。
总结
- 类以来过多其他的类,或者代码直接以来关系过于复杂,不符合高内低耦合思想,考虑拆分类。
- 类的名称过于笼统,是一个包含了多个功能的类,则可以进行细粒度拆分,一个功能一个类。
- 类或者方法的行数过多影响可读性和可维护性,则此时可以对类和方法再拆分。一个类一般不超过300-500行、一个方法最好不超过50-80行。