移除if else
首先仔細(xì)觀察一
下updateState()方法,我們會(huì)發(fā)現(xiàn),導(dǎo)致該方法內(nèi)存在大量if
else的原因是它的參數(shù)僅僅是一個(gè)enum。由于enum本身并不含有任何邏輯代碼,因此導(dǎo)致處理enum的方法需要使用if
else來(lái)分析enum然后調(diào)用相應(yīng)的邏輯。明白了這個(gè)道理之后,重構(gòu)的方向就明了了。簡(jiǎn)單的說(shuō),我們需要要將方法參數(shù)由enum替換成一個(gè)更加強(qiáng)壯的抽
象類,每一個(gè)繼承該類的子類將具體負(fù)責(zé)處理一個(gè)enum實(shí)例,之后再將updateState()方法中相應(yīng)的邏輯代碼轉(zhuǎn)移到這些子類中。這樣處理之后,
令人討厭的if else就會(huì)消失了。
import java.awt.Image;
public abstract class SystemStatePerformer {
private final SystemState state;
private Image image;
public SystemStatePerformer(SystemState state, Image image) {
this.state = state;
this.image = image;
}
public SystemState getState() {
return state;
}
public Image getImage() {
return image;
}
public abstract void perform();
}
從代碼中可以看出,每
一個(gè)performer都含義有一個(gè)SystemState,這個(gè)SystemState屬性,將只能通過(guò)構(gòu)建器映射方式射入一個(gè)performer的對(duì)
象實(shí)例。換句話說(shuō)SystemState只是一個(gè)只讀屬性,而且每一個(gè)performer實(shí)體類都只負(fù)責(zé)處理一個(gè)enum的實(shí)例(下面馬上會(huì)解釋如何實(shí)現(xiàn)
的)。這里使用的Image作為一個(gè)例子,它表示用戶的每一個(gè)狀態(tài)都可以使用一個(gè)圖標(biāo)來(lái)表示。performer()方法將負(fù)責(zé)處理具體的邏輯。這個(gè)
SystemStatePerformer的實(shí)體子類可以引用任何類型的對(duì)象,然后在perform()方法里面進(jìn)行調(diào)用。
下 一步就是編寫SystemStatePerformer的實(shí)體子類。我首先想到的是為每一個(gè)enum實(shí)例編寫一個(gè)實(shí)際的子類,理論上來(lái)說(shuō)是沒問(wèn)題的,但是 這樣做必須編寫一大堆的子類,不便于管理。所以我決定使用Factory + annonymous classes來(lái)構(gòu)建具體的實(shí)體子類,讓Factory來(lái)管理所有的實(shí)體子類。 代碼如下:
import static de.jingge.refactoring.SystemState.*;
import java.awt.Image;
import java.awt.image.BufferedImage;
public class SystemStatePerformerFactory {
private static SystemStatePerformerFactory INSTANCE = new SystemStatePerformerFactory();
private SystemStatePerformerFactory() {
}
public static SystemStatePerformer getSystemStatePerformer(SystemState state) {
switch (state) {
case LOGGEDIN:
return createLoggedInPerformer();
case IDLE:
return createIdlePerformer();
case LOGGEDOUT:
return createLoggedOutPerformer();
default:
throw new IllegalAccessError("Unkonw status");
}
}
private static SystemStatePerformer createLoggedInPerformer() {
return new SystemStatePerformer(LOGGEDIN, getImage("loggedin.gif")) {
@Override
public void perform() {
// do something after logging in is successful,
// for example: show welcome dialog, open the last edit document, etc.
}
};
}
private static SystemStatePerformer createLoggedOutPerformer() {
return new SystemStatePerformer(LOGGEDOUT, getImage("loggedout.gif")) {
@Override
public void perform() {
// do something after logging out is successful,
// for example: free used resource, dispose GUI components, etc. }
}
};
}
private static SystemStatePerformer createIdlePerformer() {
return new SystemStatePerformer(IDLE, getImage("idle.gif")) {
@Override
public void perform() {
// do something after the user is idle,
// for example: save the application state temporarily, lock the application, etc.
}
};
}
private static Image getImage(String string) {
return new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR);
}
}
從
代碼中可以看到,針對(duì)每一個(gè)enum狀態(tài)都有一個(gè)創(chuàng)建performer的方法,該方法返回一個(gè)匿名類。邏輯代碼將會(huì)被轉(zhuǎn)移至個(gè)匿名類的
perform()方法之內(nèi)。整個(gè)Factory只有一個(gè)公開的方
法:getSystemStatePerformer(SystemState),SystemManager可以調(diào)用這個(gè)方法來(lái)獲得相應(yīng)的
Performer實(shí)例。
在 這篇文章中,我希望專屬于if else的問(wèn)題。對(duì)于其他設(shè)計(jì)方面的問(wèn)題,我采取的態(tài)度是能省略就省略。實(shí)際開發(fā)中,還有有很多問(wèn)題需要處理,例如,使用static方法會(huì)導(dǎo)致系統(tǒng)的可 測(cè)試性下降,在實(shí)際開發(fā)中應(yīng)該盡量避免,解決這類問(wèn)題的方法之一是使用DI框架,例如Google Guice。
下一篇文章使用重構(gòu)移除丑陋的if else代碼(4)繼續(xù)講解。
聲明:本文版權(quán)歸作者所有,如需轉(zhuǎn)載請(qǐng)注明出處。