本文緊接
使用重構(gòu)移除丑陋的if else代碼(2)
移除if else
首先仔細觀察一
下updateState()方法,我們會發(fā)現(xiàn),導(dǎo)致該方法內(nèi)存在大量if
else的原因是它的參數(shù)僅僅是一個enum。由于enum本身并不含有任何邏輯代碼,因此導(dǎo)致處理enum的方法需要使用if
else來分析enum然后調(diào)用相應(yīng)的邏輯。明白了這個道理之后,重構(gòu)的方向就明了了。簡單的說,我們需要要將方法參數(shù)由enum替換成一個更加強壯的抽
象類,每一個繼承該類的子類將具體負責(zé)處理一個enum實例,之后再將updateState()方法中相應(yīng)的邏輯代碼轉(zhuǎn)移到這些子類中。這樣處理之后,
令人討厭的if else就會消失了。
我們將這個替換enum的抽象類命名為SystemStatePerformer,代碼如下:
package de.jingge.refactoring;
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();
}
從代碼中可以看出,每
一個performer都含義有一個SystemState,這個SystemState屬性,將只能通過構(gòu)建器映射方式射入一個performer的對
象實例。換句話說SystemState只是一個只讀屬性,而且每一個performer實體類都只負責(zé)處理一個enum的實例(下面馬上會解釋如何實現(xiàn)
的)。這里使用的Image作為一個例子,它表示用戶的每一個狀態(tài)都可以使用一個圖標(biāo)來表示。performer()方法將負責(zé)處理具體的邏輯。這個
SystemStatePerformer的實體子類可以引用任何類型的對象,然后在perform()方法里面進行調(diào)用。
下
一步就是編寫SystemStatePerformer的實體子類。我首先想到的是為每一個enum實例編寫一個實際的子類,理論上來說是沒問題的,但是
這樣做必須編寫一大堆的子類,不便于管理。所以我決定使用Factory + annonymous
classes來構(gòu)建具體的實體子類,讓Factory來管理所有的實體子類。 代碼如下:
package de.jingge.refactoring;
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);
}
}
從
代碼中可以看到,針對每一個enum狀態(tài)都有一個創(chuàng)建performer的方法,該方法返回一個匿名類。邏輯代碼將會被轉(zhuǎn)移至個匿名類的
perform()方法之內(nèi)。整個Factory只有一個公開的方
法:getSystemStatePerformer(SystemState),SystemManager可以調(diào)用這個方法來獲得相應(yīng)的
Performer實例。
在
這篇文章中,我希望專屬于if
else的問題。對于其他設(shè)計方面的問題,我采取的態(tài)度是能省略就省略。實際開發(fā)中,還有有很多問題需要處理,例如,使用static方法會導(dǎo)致系統(tǒng)的可
測試性下降,在實際開發(fā)中應(yīng)該盡量避免,解決這類問題的方法之一是使用DI框架,例如Google Guice。
下一篇文章
使用重構(gòu)移除丑陋的if else代碼(4)繼續(xù)講解。
聲明:本文版權(quán)歸作者所有,如需轉(zhuǎn)載請注明出處。