重構代碼中的if-else語句

李睿智

學號19021211293

轉載自https://blog.csdn.net/zzti_erlie/article/details/102988486

【嵌牛導讀】某公司的大佬開發(fā)了一款IM系統(tǒng),類似QQ和微信,也就是聊天軟件。就是根據(jù)消息的不同類型有不同的處理策略,每種消息的處理策略代碼都很長,如果都放在這種if else代碼快中,代碼很難維護也很丑,所以我們一開始就用了策略模式來處理這種情況。策略模式還挺簡單的,就是定義一個接口,然后有多個實現(xiàn)類,每種實現(xiàn)類封裝了一種行為。然后根據(jù)條件的不同選擇不同的實現(xiàn)類。

【嵌牛鼻子】聊天軟件、處理策略、接口、類封裝

【嵌牛提問】如果項目中的if else太多了,該怎么重構呢?

【嵌牛正文】

實現(xiàn)過程

消息對象,當然真實的對象沒有這么簡單,省略了很多屬性

@Data

@AllArgsConstructor

public class MessageInfo {

? ? // 消息類型

? ? private Integer type;

? ? // 消息內(nèi)容

? ? 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());

? ? }

}

文章寫到這,可能大多數(shù)人可能會想到要需要如下一個Map, Map<消息類型,消息處理對象>,這樣直接根據(jù)消息類型就能拿到消息處理對象,調(diào)用消息處理對象的方法即可。我們就是這樣做的,但是我們不想手動維護這個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, "消息內(nèi)容");

MessageService messageService = messageServiceContext.getMessageService(messageInfo.getType());

// 處理文本消息 消息內(nèi)容

// 可以看到文本消息被文本處理類所處理

messageService.handleMessage(messageInfo);

}

測試類正常工作,通過策略模式避免了寫大量的if else代碼,也更容易維護。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容