本文緊接
使用重構(gòu)移除丑陋的if else代碼(4)
上篇文章談到如何能夠徹底把這個switch也移除掉呢?很簡單,我們只需要在getSystemStatePerformer()方法被調(diào)用之前先創(chuàng)建所有
performer匿名類的實例,然后在該方法被調(diào)用時直接返回對應(yīng)的實力。 如何具體實現(xiàn)呢? 用Map, 請看代碼:
package de.jingge.refactoring;
import static de.jingge.refactoring.SystemState.*;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author gejing@gmail.com
*/
public class SystemStatePerformerFactory {
private static SystemStatePerformerFactory INSTANCE = new SystemStatePerformerFactory();
private Map<SystemState, SystemStatePerformer> performers;
private SystemStatePerformerFactory() {
}
public static SystemStatePerformerFactory getInstance() {
return INSTANCE;
}
private synchronized Map<SystemState, SystemStatePerformer> getPerformers()
throws Exception {
if (performers == null) {
performers = new HashMap<SystemState, SystemStatePerformer>();
// call all @FactoryMethod using reflection
for (Method m : getClass().getDeclaredMethods()) {
if (m.getAnnotation(FactoryMethod.class) != null) {
SystemStatePerformer p = (SystemStatePerformer) m.invoke(
this, new Object[]{});
performers.put(p.getState(), p);
}
}
// make it readonly
performers = Collections.unmodifiableMap(performers);
}
return performers;
}
public SystemStatePerformer getSystemStatePerformer(SystemState state) throws Exception{
return getPerformers().get(state);
}
@FactoryMethod
private 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.
}
};
}
@FactoryMethod
private 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. }
}
};
}
@FactoryMethod
private 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 Image getImage(String string) {
return new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR);
}
}
從代碼中可以看出,當(dāng)getPerformers()方法被第一次調(diào)用時,我們會為每一個performer匿名類創(chuàng)建一個實例,并且將它們納入Map的管
理之中,以后每次調(diào)用的時候,直接從Map里面提取對應(yīng)某個狀態(tài)的performer就可以了, switch可以舍棄了。
@FactoryMethod這個注釋是我自己寫的,使用它主要是為了避免每次新增加一個create***Performer()方法后,都必須修改
getSystemStatePerformer()。
@FactoryMethod的代碼如下:
package de.jingge.refactoring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface FactoryMethod {
}
到這里整個重構(gòu)已經(jīng)結(jié)束了, 我們已經(jīng)將if else, switch完全從代碼里剔除了。
讀過Refactoring to Patterns這本書的朋友可能會覺得,這里所作的一些和書中第七章最后一節(jié)Replace
Conditional Dispatcher with Command完全一樣。
Well,第一眼看上去確實很像,但是看完我寫的所有代碼后,再仔細(xì)想一想,兩者還是有區(qū)別的(Refactoring to Patterns這本書寫的非常好,對此書,我可以說是愛不釋手,還曾經(jīng)寫過一篇書評。事實上,我這篇文章正式基于這本書的):
1. Factory + annonymous類而不是每一個狀態(tài)一個具體的實體類。
這樣處理問題, 類的數(shù)量大大減少,類關(guān)聯(lián)的復(fù)雜程度也大大減少,維護(hù)起來很方便。
2. performer并不單單是一個command,它擁有狀態(tài),并且可以處理更多的邏輯。
全文完。
聲明:本文版權(quán)歸作者所有,如需轉(zhuǎn)載請注明出處。