最近有朋友说帮他优化一下代码,由于需要处理多种不同类型的数据或对象,他不得不在代码中编写了大量的if-else或switch语句来进行类型判断。这不仅使得代码变得冗长复杂,还降低了代码的可读性和可维护性。每次新增或修改类型时,都需要在多个地方更新这些判断逻辑,增加了出错的风险。
他源代码大致意思是根据不同的userType去删除不同表的数据,我们在本地项目复现一下:
if (CollectionUtils.isNotEmpty(deleteRelations)){
// 循环根据角色删除对应的角色表数据
for (OrgNewUserRelation deleteRelation: deleteRelations){
// 如果角色是表A类型,删除表A数据
if ("A".equals(deleteRelation.getNewUserType())){
// 根据userCode查询表A数据
TableA tableA = tableARepository.findByUserCode(deleteRelation.getUserCode());
if (financialManager != null){
// 删除表A数据
tableARepository.delete(financialManager);
}
}
// 如果角色是表B类型,删除表B数据
else if ("B".equals(deleteRelation.getNewUserType())){
// 根据userCode查询表B数据
TableB tableB = financialCommissionerRepository.findByUserCode(deleteRelation.getUserCode());
if (tableB != null){
// 删除表B数据
tableBRepository.delete(financialCommissioner);
}
}
// 如果角色是表C类型,删除表C数据
else if ("C".equals(deleteRelation.getNewUserType())){
// 根据userCode查询表C数据
TableC tableC = tableCRepository.findByUserCode(deleteRelation.getUserCode());
if (ableC != null){
// 删除表C数据
tableCRepository.delete(agronomist);
}
}
}
}
当面对多种角色(或用户类型)需要分别操作多个不同表的情况时,使用if或switch语句来逐一判断角色并调用相应的逻辑会导致代码冗长且难以维护。为了优化这种情况,我们可以采用一些设计模式或结构来减少重复代码和提高代码的可读性与可扩展性。以下是一种基于“工厂模式”和“策略模式”结合的优化方案:
定义一个策略删除表接口以及一个删除数据方法。
/**
* 删除表数据策略接口
*/
public interface DataStrategy {
// 根据userCode删除数据方法
void deleteByUserCode(String userCode);
}
删除表A的策略实现类
@Service
public class TableADeleteStrategy implements DataStrategy {
// 可以理解为TableA的mapper
private TableARepository tableARepository;
// 构造器注入方法不要删,策略工厂new的时候要用到
public TableADeleteStrategy(TableARepository tableARepository) {
this.ableARepository = ableARepository;
}
@Override
public void deleteByUserCode(String userCode) {
if (StringUtils.isBlank(roleCode)) {
return;
}
// 根据userCode查询数据
Agronomist agronomist = tableARepository.findByUserCode(userCode);
if (null == agronomist){
return;
}
// 数据删除
agronomistRepository.delete(agronomist);
}
}
删除表B的策略实现类
@Service
public class TableBDeleteStrategy implements DataStrategy {
// 可以理解为TableB的mapper
private TableBRepository tableBRepository;
// 构造器注入方法不要删,策略工厂new的时候要用到
public TableBDeleteStrategy(TableBRepository ableBRepository) {
this.tableBRepository = tableBRepository;
}
@Override
public void deleteByUserCode(String userCode) {
if (StringUtils.isBlank(userCode)) {
return;
}
// 根据userCode查询数据
TableB tableB = ableBRepository.findByUserCode(userCode);
if (null == ableB) {
return;
}
// 数据删除
ableBRepository.delete(ableB);
}
}
删除表C的策略实现类
@Service
public class TableCDeleteStrategy implements DeleteDataStrategy {
// 可以理解为TableC的mapper
private TableCRepository tableCRepository;
// 构造器注入方法不要删,策略工厂new的时候要用到
public TableCDeleteStrategy(TableCRepository tableCRepository) {
this.tableCRepository = tableCRepository;
}
@Override
public void deleteByUserCode(String userCode) {
if (StringUtils.isBlank(userCode)) {
return;
}
// 根据userCode查询数据
TableC tableC = tableCRepository.findByUserCode(userCode);
if (null == ableC) {
return;
}
// 数据删除
tableCRepository.delete(tableC);
}
策略接口和实现类定义完了,那么怎么去用呢,这里我是把策略模式实现类放到了工厂里,具体如下:
定义一个策略工厂接口:
public interface DeleteDataStrategyFactory {
/**
* 根据用户类型获取对应的表数据策略Bean
* @param userType
* @return
*/
DeleteDataStrategy createStrategy(Integer userType);
}
策略工厂实现类:
@Service
public class DeleteDataStrategyFactoryImpl implements DeleteDataStrategyFactory {
private final Map<Integer, DeleteDataStrategy> strategyMap = new HashMap<>();
// @PostConstruct 注解的方法会在依赖注入完成后自动调用。通过在 init() 方法中初始化 strategyMap,可以确保在使用这些 Repository 对象时它们已经被注入。
@PostConstruct
public void init() {
strategyMap.put("A", new TableADeleteStrategy(tableARepository));
strategyMap.put("B", new TableBDeleteStrategy(tableBRepository));
strategyMap.put("C", new TableCDeleteStrategy(tableCRepository));
}
@Resource
private TableARepository tableARepository;
@Resource
private TableBRepository tableBRepository;
@Resource
private TableCRepository tableCRepository;
@Override
public DeleteOldDataStrategy createStrategy(Integer userType) {
// 这里因为switch case 不支持枚举,我又不想吧case写死,所以用map代替
if (!strategyMap.containsKey(userType)){
throw new IllegalArgumentException("未找到对应的策略类");
}
return strategyMap.get(userType);
}
}
将策略工厂模式套入到原先的删除逻辑中,确实可以大幅度简化代码,使得原本可能需要多个if或switch语句来判断并执行不同删除逻辑的地方,现在只需要两行代码(调用工厂获取策略和调用策略的方法)即可完成。这样的优化不仅让代码看起来更加干净、整洁,还提高了代码的可读性和可维护性。
if (CollectionUtils.isNotEmpty(deleteRelations)){
// 循环根据角色删除对应的角色表数据
for (OrgNewUserRelation deleteRelation: deleteRelations){
// 根据角色类型从工厂获取对应的删除策略类
SyncDeleteOldDataStrategy strategy = deleteDataStrategyFactory.createStrategy(deleteRelation.getUserType());
// 获取到策略实现类,进行数据删除
strategy.deleteByNewUserCode(deleteRelation.getUserCode());
}
}
策略模式优点:
可扩展性:当需要添加新的角色类型时,只需添加新的策略类和在工厂类中添加对应的生成逻辑。
解耦:策略类和客户端代码(如DataDeleter和Application)之间解耦,便于各自独立变化。
易维护:减少了if或switch语句的嵌套,使得代码更加清晰易懂。