當(dāng)代碼中出現(xiàn)很多if-else語句檐薯,并且每個(gè)if代碼塊中的邏輯都很復(fù)雜的時(shí)候凝赛,這時(shí)如果要對(duì)代碼進(jìn)行維護(hù)或者是讓別人使用你的代碼都會(huì)比較麻煩注暗,而且有可能會(huì)因?yàn)橐稽c(diǎn)改動(dòng)導(dǎo)致整個(gè)系統(tǒng)出現(xiàn)異常。所以需要考慮如何對(duì)大量的if-else進(jìn)行重構(gòu)墓猎,讓各個(gè)if-else的邏輯獨(dú)立開來捆昏,互不影響。
這里想到了設(shè)計(jì)模式當(dāng)中的策略模式毙沾,定義一個(gè)策略接口骗卜,每個(gè)if代碼塊都是一種策略的實(shí)現(xiàn)類,然后定義一個(gè)策略上下文左胞,目的是根據(jù)不同的需求膨俐,即if條件,來選擇不同的策略的實(shí)現(xiàn)罩句。
現(xiàn)在,我提供一個(gè)在工作中出現(xiàn)的場(chǎng)景demo:
在一個(gè)文字游戲客戶端中敛摘,我需要根據(jù)玩家輸入的字符串來判斷玩家需要執(zhí)行的指令门烂,例如user_login代表用戶登錄,客戶端根據(jù)指令返回對(duì)應(yīng)的protobuf類兄淫,然后發(fā)送給服務(wù)器端屯远。這里因?yàn)槲倚枰褂弥噶顏碛成鋚rotobuf類,因此用到了靜態(tài)工廠模式捕虽,利用Spring的IOC管理每種策略實(shí)現(xiàn)慨丐,將每一個(gè)指令-protobuf類映射注冊(cè)為一種產(chǎn)品,然后使用靜態(tài)工廠來生產(chǎn)這種產(chǎn)品泄私。
代碼如下:
策略模式
/**
* 指令策略接口
*
* @author Administrator
*/
public interface CommandStrategy {
/**
* 處理過程, 根據(jù)對(duì)應(yīng)的proto類 來調(diào)用不同的策略去執(zhí)行proto文件的封裝
* @param content 玩家輸入的參數(shù)房揭,除指令以外的信息
* @return
* @throws Exception 參數(shù)錯(cuò)誤等異常
*/
Object processProto(String content) throws Exception;
}
/**
* 處理UserLoginReq的Proto的策略實(shí)現(xiàn)類
*
* @author Administrator
*/
@Component("userLoginReqProto")
public class UserLoginReqProto implements CommandStrategy, InitializingBean {
@Override
public UserLoginReq processProto(String content) throws Exception {
if (StringUtils.isEmpty(content)) {
throw new Exception("參數(shù)不能為空");
}
String[] split = content.split("\\s+");
if (split.length != 2) {
throw new Exception("參數(shù)個(gè)數(shù)出錯(cuò)!");
}
UserLoginReq userLoginReq = UserLoginReq
.newBuilder()
.setAccount(split[0])
.setPassword(split[1])
.build();
return userLoginReq;
}
/**
* 靜態(tài)工廠:注冊(cè)為靜態(tài)工廠的一種產(chǎn)品
*/
@Override
public void afterPropertiesSet() throws Exception {
CommandFactory.registerReqClass(Command.USER_LOGIN.getCmd(), this);
}
}
靜態(tài)工廠模式
/**
* 靜態(tài)工廠晌端,根據(jù)指令生產(chǎn)對(duì)應(yīng)的Proto對(duì)象
*
* @author Administrator
*/
public class CommandFactory {
/**
* 策略CommandStrategy的具體對(duì)象捅暴,通過策略對(duì)象返回對(duì)應(yīng)的proto req
*/
private static Map<Integer, CommandStrategy> protoMap = new HashMap<>();
private CommandFactory() {}
/**
* 根據(jù)指令得到CommandStrategy對(duì)象
* @param cmd
* @return
*/
public static CommandStrategy getReqClass(Integer cmd) {
return protoMap.get(cmd);
}
/**
* 將具體CommandStrategy對(duì)象注冊(cè)到Map
*/
public static void registerReqClass(Integer cmd, CommandStrategy proto) {
protoMap.put(cmd, proto);
}
}
/**
* 靜態(tài)工廠,返回Proto Req的具體對(duì)象
* 根據(jù)指令獲取對(duì)象實(shí)例
* @author Administrator
*/
public class WorkReqProto {
/**
* 返回Proto Req的具體對(duì)象
*
* @param cmd 需要返回的proto類型
* @param content 輸入的字符串參數(shù)內(nèi)容咧纠,如wan 123456
* @return
*/
public static Object getReqProto(Integer cmd, String content) throws Exception {
CommandStrategy commandStrategy = CommandFactory.getReqClass(cmd);
return commandStrategy.processProto(content);
}
}