項目重構,我是如何優化大量屎一樣的 if else 代碼的?

目錄:

  • if else
  • 策略模式
  • 1、首先抽象業務處理器
  • 2、將業務處理器和其支持處理的類型放到一個容器中,java裡Map就是最常用的容器之一
  • 3、定義不同的處理器
  • 4、測試類

前段時間,我將公司系統中的批量審單的功能進行了重構,用到了java的併發編程進行異步化處理,數據庫的樂觀鎖機制處理多線程併發更新數據。

其中批量審單的業務處理涉及到多種任務類型,對應不同的業務方法進行處理,比如轉倉,轉快遞,添加贈品,刪除贈品,拆分訂單,批量駁回,批量作廢等等,其中就用到了策略模式。

if else

 if ("BATCH_CHANGE_WAREHOUSE".equals(taskType)) {
//批量轉倉邏輯
} else if ("BATCH_CHANGE_SHIPPING".equals(taskType)) {
//批量轉快遞邏輯
} else if ("BATCH_REPLACE_ORDER_GOODS".equals(taskType)) {
//批量替換訂單商品邏輯
} else if ("BATCH_DELETE_ORDER_GOODS".equals(taskType)) {
//批量刪除訂單商品邏輯
} else if ("BATCH_ADD_MEMO".equals(taskType)) {
//批量添加備註邏輯
} else {
//任務類型未知
System.out.println("任務類型無法處理");
}

看起來,思路清晰,if,else分支也很清楚,但不覺得代碼很臃腫,維護起來麻煩嗎

尤其是其他人來接鍋的時候,連看下去的慾望都沒有了。這時候你需要用策略模式消除其中的if else,進行一下簡單的重構!

策略模式

1、首先抽象業務處理器

public abstract class InspectionSolver {
public abstract void solve(Long orderId, Long userId);

public abstract String[] supports();
}

2、將業務處理器和其支持處理的類型放到一個容器中,java裡Map就是最常用的容器之一

@Component

public class InspectionSolverChooser implements ApplicationContextAware {

private MapchooseMap = new HashMap<>();

public InspectionSolver choose (String type) {

return chooseMap.get(type);

}

@PostConstruct

public void register () {

MapsolverMap = context.getBeansOfType(InspectionSolver.class);

for (InspectionSolver solver : solverMap.values()) {

for (String support : solver.supports()) {

chooseMap.put(support,solver);

}

}

}

private ApplicationContext context;

@Override

public void setApplicationContext (ApplicationContext applicationContext) throws BeansException {

this .context=applicationContext;

}

}

這裡是在應用啟動的時候,加載spring容器中所有InspectionSolver類型的處理器,放到InspectionSolverChooser的map容器中。

注意是InspectionSolver類型,所以定義的處理器都得繼承InspectionSolver

其次是spring容器中的才能加載,所以定義的處理器都得放到spring容器中(@Component註解不能少)

3、定義不同的處理器

@Component
public class ChangeWarehouseSolver extends InspectionSolver {
@Override
public void solve(Long orderId, Long userId) {
System.out.println("訂單"+orderId+"開始進行批量轉倉了。。");
}
@Override
public String[] supports() {
return new String[] {InspectionConstant.INSPECTION_TASK_TYPE_BATCH_CHANGE_WAREHOUSE};
}
}
@Component
public class ChangeShippingSolver extends InspectionSolver{
@Override
public void solve(Long orderId, Long userId) {
System.out.println("訂單"+orderId+"開始進行轉快遞了。。");
}
@Override
public String[] supports() {
return new String[] {InspectionConstant.INSPECTION_TASK_TYPE_BATCH_CHANGE_SHIPPING};
}
}
@Component
public class ReplaceOrderGoodsSolver extends InspectionSolver{
@Override
public void solve(Long orderId, Long userId) {

System.out.println("訂單"+orderId+"開始進行替換商品了");
}
@Override
public String[] supports() {
return new String[]{InspectionConstant.INSPECTION_TASK_TYPE_BATCH_REPLACE_ORDER_GOODS};
}
}

4、測試類

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=Application.class)// 指定spring-boot的啟動類
public class InspectionTest {
@Autowired
private InspectionSolverChooser chooser;
@Test
public void test() throws Exception{
//準備數據
String taskType = InspectionConstant.INSPECTION_TASK_TYPE_BATCH_CHANGE_WAREHOUSE;
Long orderId = 12345L;
Long userId = 123L;
//獲取任務類型對應的solver
InspectionSolver solver = chooser.choose(taskType);
if (solver == null) {
throw new RuntimeException("任務類型暫時無法處理!");
}
//調用不同solver的方法進行處理
solver.solve(orderId,userId);
}
}

在測試類中我消除了可能一長段的if else,從選擇器InspectionSolverChooser中根據type的不同取出不同的任務處理器InspectionSolver

然後調用其solve()方法進行任務處理,不同處理器調用的當然就是不同的solve()方法了,目的達到。


分享到:


相關文章: