物件導向與IF-ElSE
我們這裡要討論的問題是,對於代碼中出現了很多的IF-Else,我們如何處理
我之前寫了個代碼,要求對輸入的不同字元作不同處理,所以寫了很多IF-Else,後來,需求增加,也就是增加了一些判斷,我把所有的半段都提出來放到了一個方法裡,利用flag進行表示處理,雖然解決了需求的擴充問題,但是大量的IF-Else沒有得到處理,當然如果輸入的字元種類很少,我想沒必要處理[當時只有4種],但是如果輸入的字元種類便多了,怎麼辦?當然不能再用IF-Else了。
[1、] 其實處理辦法是有的,如果應用程式命令模式,但其實只是分散了IF-ELSE,但並沒有解決實質性問題。
public void process(char inChar){//原來未使用命令模式的處理
if(inChar == 'A'){......}
if(inChar == 'B'){......}
if(inChar == 'C'){......}
if(inChar == 'D'){......}
...............................
}
使用命令模式:
public Interface Handle{public void doSome(char inChar);}
public class HandleACommand{
public void doSome(char inChar){//這裡其實是分散了if的處理方式,使其不用集中處理
if(inChar == 'A'){//do some thing . }
}
}
public class HandlBCommand{
public void doSome(char inChar){//這裡其實是分散了if的處理方式,使其不用集中處理
if(inChar == 'B'){//do some thing . }
}
}
//now we call process with command pattern
public void process(char inChar){//原來未使用命令模式的處理
private Handle handleA = new HandleACommand();//這裡也可以使用DI方式注入
private Handle handleB = new HandleBCommand();//這裡也可以使用DI方式注入
.....................................
handleA.doSome(inChar);
handleB.doSome(inChar);
handleC.doSome(inChar);
handleD.doSome(inChar);
...............................
}
[2、] 使用Java反射機制
另外一種解決方案是Java的反射機制。通過輸入的字元合成不同的方法,擴充問題很好解決,每增加一個命令,就增加一個方法,但是會出現大量的方法。效能上不用我說大家也知道,會比不用反射機制慢1個數量級,當然它可以解決問題。
public void process(char inChar){
tyr{
final Method handleMethod = this.getClass().getMethod("handle" + inChar);
handleMethod.invoke(this);
}catch(NoSuchMethodException ex){//do exception.......}
}catch(IllegalAccessException ex}{//do exception.......}
}catch (InvocationTargetException ex){//do exception.......}
private void handleA(inChar){//do some thing.}
private void handleB(inChar){//do some thing.}
private void handleC(inChar){//do some thing.}
private void handleD(inChar){//do some thing.}
}
[3、] 利用state模式處理
下面是用的最多的處理辦法,利用State模式進行處理。這也是處理此類問題使用最多的一種模式。當然也不是萬能的,只是讓大家首先考慮這個模式而已。但是這樣會增加子類的數量。
public interface State {public void handle();}
public class ConcreteState_ONE {
public void handle(){//do some thing. }
}
public class ConcreteState_TWO {
public void handle(){//do some thing. }
}
public class ConcreteState_Default {
public void handle(){//do some thing. }
}
..............................................
public class CoreProcess {
private static final int STATE_ONE = 0;
private static final int STATE_TWO = 1;
private static final int STATE_THREE = 2;
private static final int STATE_FOUR = 3;
..........................................
private State initState = new ConcreteState_Default();
public void changeState(int stateNum){
switch(stateNum){
case STATE_ONE : initState = new ConcreteState_ONE(); break;
case STATE_TWO : initState = new ConcreteState_TWO(); break;
......................................................
default : initState = new ConcreteState_Default();
}
}
public void requestCommand(){
initState.handle();
}
}
//客戶調用
public class Context{
public static void main(String[] args){
CoreProcess coreProcess = new CoreProcess();
coreProcess.changeState(CoreProcess.STATE_ONE);
coreProcess.requestCommand();
..............................................
coreProcess.changeState(CoreProcess.STATE_THREE);
coreProcess.requestCommand();
....................................
}
}
總結,但是在提出的汽車問題中,輸入的字元擴充有限(或者說輸入字元種類不回很多),不應該過度設計,當然那也是時間有限,過度設計最可怕的是它會分散你的思維,讓你有限的精力浪費在不應該或暫時不應該思考的問題上,而那些真正應該在現階段得到重視和解決的問題卻被你忽略了。無論是java還是c++以及其他很多語言,都有if/else 關鍵字的出現,那麼就不能用是否物件導向而將之排出,比如在Struts的Action處理中,根據不同情況進行不同跳轉處理就是應該使用if/else。
coolwangyu@Gmail.com