項目中有個業(yè)務(wù)處理類大小117K,代碼2700行,看此類差點雷死我,如今如要增加業(yè)務(wù)邏輯大約20個吧,此類如果隨著項目工程的二期、三期如次添加邏輯遲早有一天大小達(dá)到M,噢、mygod。細(xì)心研讀前人的工作總結(jié),發(fā)現(xiàn)其中有點可改造的蛛絲馬跡(本人很笨、別笑我才發(fā)現(xiàn)如何改造)。
下面我們對業(yè)務(wù)流程、以及涉及的相關(guān)類進(jìn)行介紹,Msg代表接受到客戶端的一個消息報文,消息報文結(jié)構(gòu):消息頭+消息體,消息頭參數(shù)固定、消息體參數(shù)不定,下面是一個簡單的類圖,這只是一個模擬場景,****Req代表各戶端請求類,***Rsp代表返回給客戶端的參數(shù)類。實際比此復(fù)雜,為描述問題我們簡單摘除幾個類介紹,別問我為何這么設(shè)計繼承。類圖msg與msgHead是組合關(guān)系也許畫錯了、不當(dāng)之處請指出,勿惡語向傷;

處理請求Handler類的代碼邏輯如下:
//類中主要方法如下
public void execute(Object object) {
Message message = (Message)object;
int opcode = message.getOpcode();
int connectId = message.getConnectId();
//消息頭已經(jīng)解析,獲取消息體,即子類屬性字節(jié)數(shù)組
byte[] bytes = message.getBytes();
if (opcode == MsgInfo.ADD_RING) {
// 訂購彩鈴
orderRing(connectId, bytes);
} else if (opcode == MsgInfo.PRESENT_RING) {
// 贈送彩鈴
presentRing(connectId, bytes);
} else if (opcode == MsgInfo.DEL_RING) {
// 刪除個人鈴音
delPersonalRing(connectId, bytes);
}
//此處省略n個else if
}
//其他刪除、贈送與省略的else if中的處理邏輯與之基本相同
private void orderRing(int connectId, byte[] bytes) {
//處理方法分為四步,具體代碼省略
//1、解析字節(jié)數(shù)組為訂購鈴音類
//2、處理訂購關(guān)系
//3、處理結(jié)果封裝為訂購響應(yīng)類
//4、發(fā)送回客戶端
}
//省略presentRing、delPersonalRing等一系列其他方法,所有的處理方法參數(shù)相同……
鑒于此、想到使用命令模式改造此類,如果不了解命令模式請閱讀相關(guān)書籍,大話設(shè)計模式或設(shè)計與模式,這里我們僅給出大致的定于與類圖。
何謂命令模式:將一個請求封裝為一個對象,從而是你可用不同的請求對客戶端參數(shù)化,對請求排隊或記錄日志,以及支持可撤銷的操作。
Shit、這句話很難理解哦,那就先別理解了,我們看下命令模式的類圖,然后介紹如何使用命令模式改造上面的elseif。
類圖先省略,上班偷空寫的;
下面進(jìn)入正題,對Handler小手術(shù)開始,主要考慮如下:
1、提煉方法
將每個if語句塊中的邏輯提取為一個方法,這里我們的handler已經(jīng)實現(xiàn),就是:orderRing、presentRing、delPersonalRing、……。
2、提煉類
將每個業(yè)務(wù)處理方法提取為以各類,然后對具體類進(jìn)行抽象,提取父類或者接口;代碼如下:
public Abstract class Command{
public void execute()
}
public class OrderRingCommand extends Command {
private Handler hander;
public OrderRingCommand(Handler hander){
this.hander = hander;
}
public void execute(int connectId, byte[] bytes){
//1、解析字節(jié)數(shù)組為訂購鈴音類
//2、增加訂購關(guān)系
//3、處理結(jié)果封裝為訂購響應(yīng)類
//4、發(fā)送回客戶端
}
/**
* 1、解析字節(jié)數(shù)組為訂購鈴音類
*/
public void method1(){
}
/**
* 2、處理訂購關(guān)系
*/
public void method2(){
}
/**
* 3、處理結(jié)果封裝為訂購響應(yīng)類
*/
public void method3(){
}
/**
* 4、結(jié)果發(fā)送回客戶端
*/
public void method4(){
}
}
public class DelRingCommand extends Command {
private Handler hander;
public DelRingCommand(Handler hander){
this.hander = hander;
}
public void execute(int connectId, byte[] bytes){
//1、解析字節(jié)數(shù)組為訂購鈴音類
//2、刪除購關(guān)系
//3、處理結(jié)果封裝為訂購響應(yīng)類
//4、發(fā)送回客戶端
}
//提取方法
}
3、命令模式改造替換elseif:
Map<Integer, Command> map = new HashMap<Integer,Command>();
static{
map.put(MsgInfo.ADD_RING, new OrderRingCommand());
//省卻其他,這里僅為演示,實際項目中實例化類通過spring容器或者其他方法
}
public void execute(Object object) {
Message message = (Message)object;
int opcode = message.getOpcode();
int connectId = message.getConnectId();
//消息頭已經(jīng)解析,獲取消息體,即子類屬性字節(jié)數(shù)組
byte[] bytes = message.getBytes();
map.get(opcode).execute(connectId,bytes);
}
命令模式替換else if代碼壞味道的重構(gòu)結(jié)束,眾多的if條件塊煙消云散,取而代之的是一個個精簡的類,doc版本在附件中