專案中的if else太多了,該怎麼重構?
介紹
最近跟著公司的大佬開發了一款IM系統,類似QQ和微信哈,就是聊天軟體。我們有一部分業務邏輯是這樣的
if (msgType = "文字") {
// dosomething
} else if(msgType = "圖片") {
// doshomething
} else if(msgType = "視訊") {
// doshomething
} else {
// doshomething
}
就是根據訊息的不同型別有不同的處理策略,每種訊息的處理策略程式碼都很長,如果都放在這種if else程式碼快中,程式碼很難維護也很醜,所以我們一開始就用了策略模式來處理這種情況。
策略模式還挺簡單的,就是定義一個介面,然後有多個實現類,每種實現類封裝了一種行為。然後根據條件的不同選擇不同的實現類。
實現過程
訊息物件,當然真實的物件沒有這麼簡單,省略了很多屬性
@Data
@AllArgsConstructor
public class MessageInfo {
// 訊息型別
private Integer type;
// 訊息內容
private String content;
}
定義一個訊息處理介面
public interface MessageService {
void handleMessage(MessageInfo messageInfo);
}
有2個訊息處理介面,分別處理不同的訊息
處理文字訊息
@Service
@MsgTypeHandler(value = MSG_TYPE.TEXT)
public class TextMessageService implements MessageService {
@Override
public void handleMessage(MessageInfo messageInfo) {
System.out.println("處理文字訊息 " + messageInfo.getContent());
}
}
處理圖片訊息
@Service
@MsgTypeHandler(value = MSG_TYPE.IMAGE)
public class ImageMessageService implements MessageService {
@Override
public void handleMessage(MessageInfo messageInfo) {
System.out.println("處理圖片訊息 " + messageInfo.getContent());
}
}
文章寫到這,可能大多數人可能會想到要需要如下一個Map, Map<訊息型別,訊息處理物件>,這樣直接根據訊息型別就能拿到訊息處理物件,呼叫訊息處理物件的方法即可。我們就是這樣做的,但是我們不想手動維護這個Map物件,因為每次增加新的訊息處理類,Map的初始化過程就得修改
我們使用了註解+ApplicationListener來儲存這種對映關係,來看看怎麼做的把
定義一個訊息型別的列舉類
public enum MSG_TYPE {
TEXT(1, "文字"),
IMAGE(2, "圖片"),
VIDEO(3, "視訊");
public final int code;
public final String name;
MSG_TYPE(int code, String name) {
this.code = code;
this.name = name;
}
}
定義一個註解
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MsgTypeHandler {
MSG_TYPE value();
}
不知道你注意到了沒,前面的程式碼中,每種訊息處理類上面都有一個@MsgTypeHandler註解,表明了這個處理類
處理哪種型別的訊息
@Service
@MsgTypeHandler(value = MSG_TYPE.TEXT)
public class TextMessageService implements MessageService {
@Override
public void handleMessage(MessageInfo messageInfo) {
System.out.println("處理文字訊息 " + messageInfo.getContent());
}
}
用一個context物件儲存了訊息型別->訊息處理物件的對映關係
@Component
public class MessageServiceContext {
private final Map<Integer, MessageService> handlerMap = new HashMap<>();
public MessageService getMessageService(Integer type) {
return handlerMap.get(type);
}
public void putMessageService(Integer code, MessageService messageService) {
handlerMap.put(code, messageService);
}
}
最精彩的部分到了
@Component
public class MessageServiceListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(MsgTypeHandler.class);
MessageServiceContext messageServiceContext = event.getApplicationContext().getBean(MessageServiceContext.class);
beans.forEach((name, bean) -> {
MsgTypeHandler typeHandler = bean.getClass().getAnnotation(MsgTypeHandler.class);
messageServiceContext.putMessageService(typeHandler.value().code, (MessageService) bean);
});
}
}
在spring的啟動過程中,通過解析註解,將訊息型別->訊息處理物件的對映關係儲存到MessageServiceContext物件中
@Autowired
MessageServiceContext messageServiceContext;
@Test
public void contextLoads() {
// 構建一個文字訊息
MessageInfo messageInfo = new MessageInfo(MSG_TYPE.TEXT.code, "訊息內容");
MessageService messageService = messageServiceContext.getMessageService(messageInfo.getType());
// 處理文字訊息 訊息內容
// 可以看到文字訊息被文字處理類所處理
messageService.handleMessage(messageInfo);
}
測試類正常工作,通過策略模式避免了寫大量的if else程式碼,也更容易維護
歡迎關注
參考部落格
[1]https://juejin.im/post/5c5172d15188256a2334a15d
相關文章
- Objc Runtime在專案中該怎麼用OBJ
- 我來告訴你,ChatGPT 該怎麼對接到自己的專案中!ChatGPT
- 寫簡歷應該怎麼準備專案
- 在專案管理中,專案成員不能及時完不成任務,應該怎麼做?專案管理
- 外包公司專案管理的問題應該怎麼管專案管理
- 專案管理流程發生偏離,該怎麼辦?專案管理
- 軟體專案研發流程該怎麼規範
- 減少程式碼中該死的 if else 巢狀巢狀
- Nuxt3專案中,在構建專案時,無法獲取到 .env 檔案的變數,怎麼破?UX變數
- 最近專案重構的一些感想
- 重構Vue專案的通用處理流程Vue
- 【經驗分享,歡迎討論】專案管理中需求變更太頻繁,怎麼辦?專案管理
- 專案重構經驗記錄
- 記一次專案重構
- 軟體專案中,需求怎麼做?
- 通篇if-else,看得太煩怎麼辦,看Java8如何化腐朽為神奇Java
- 老闆說laravel太慢讓我用rust寫web重構公司幾年前的專案怎麼辦?LaravelRustWeb
- 記一次重構,策略模式替換if else模式
- 專案的改造——RemoveButterKnife外掛程式碼的重構REM
- 想要提取PDF檔案中的美麗圖片,該怎麼辦?
- Webpack 中的 sideEffects 到底該怎麼用?WebIDE
- 減少該死的 if else 巢狀巢狀
- typeScript 配置檔案該怎麼寫?TypeScript
- 區塊鏈專案應該怎麼海外運營及推廣?區塊鏈
- Java程式設計細節-重構-為什麼 if-else 不是好程式碼Java程式設計
- win10沒有wifi只有乙太網該怎麼辦Win10WiFi
- 區塊鏈專案應該怎樣落地?區塊鏈
- 你是怎麼處理vue專案中的錯誤的?Vue
- go專案結構是怎麼樣的?go入門學習Go
- 重構商城App專案——知識總結APP
- 實戰 | 使用maven 輕鬆重構專案Maven
- 怎麼在Android專案中匯入ffmpeg庫?Android
- 利用IDEA建立gradle構建的Java多模組專案(太清晰了)IdeaGradleJava
- 專案管理中,應該注意的5點原則專案管理
- 得物複雜 C 端專案的重構實踐
- 探索大型專案怎麼進行專案管理?專案管理
- 怎麼寫開源專案的README
- 在Django中查詢重複專案Django