背景
工作中經常會有一些swich case或者if else的情況。一般這種情況一開始可能只有幾個,但是幾次迭代之後可能就會有非常多。代碼不易維護而且代碼亂糟糟的。
我在工作中就遇到了這種情況。大致的業務就是我們需要對接很多家公司,要爲每家公司回傳一些數據。每家公司的接口和回傳方式都不一樣。之前的代碼是爲每一家公司定義一個枚舉。然後在回傳的時候根據枚舉用swich/case來判別回傳方式。這樣的結果就是對接的公司越來越多,代碼也越來越長。一個函數長度達到了兩百多行。非常難受。
開閉原則
設計模式裏面有一個原則叫做開閉原則,就是軟件實體應當對拓展開放,對修改關閉。之前的代碼是有一種情況,就在原來的代碼裏面加上,也就是說原來的代碼是對修改開放的。而且更像是面向過程的,沒有很好地發揮面向對象的優勢。
方案
後來終於受不了了想拿他開刀。這個問題不難,關鍵解決方案就是多態+反射。多態就是定義一個接口一個notify函數。然後每一家公司實現這個接口就可以了。反射的話其實用不到JDK的反射,spring自帶反射,用名字就可以得到這個類的實例。廢話不多說下面上代碼。
枚舉
首先要定義一個枚舉,每一種情況一個字段,注意,枚舉要有一個屬性,beanName,方便反射的時候獲取實例。這裏把名字都簡化了。
@Getter
@AllArgsConstructor
public enum SomeEnum {
NONE(0, ""),
A(1, "aServiceImpl"),
B(2, "bServiceImpl"),
C(3, "cServiceImpl"),
D(4, "dServiceImpl"),
// 公司的這裏有二十多個,現在就簡略一下。
;
private int type;
private String beanName;
}
接口
第二步,定義一個接口。
public interface BaseService {
boolean doSomething(String a);
}
實現
第三步,上面每一個枚舉都添加一個類實現這個接口,注意命名方式和beanName相同,因爲spring默認的bean名字是第一個小寫,所以實現類還是遵循命名規範用大寫。而且一定要打上@Service
@Service
@Slf4j
public class AServiceImpl implements BaseService {
@Override
public boolean doSomething(String a) {
// 業務邏輯寫在這裏
return true;
}
}
多態
第四步,就差這步了。把原來的switch/case全刪掉。換上下面這幾行代碼。
@Autowired
private ApplicationContext applicationContext;
BaseService service = (BaseService) applicationContext.getBean(someEnum.getBeanName());
result = service.doSomething("xxx");
總結
原本幾百行的代碼在這裏就變得十分清爽了。
如果現在要添加一個公司,只需要添加一個枚舉字段,添加一個類實現base接口,就可以了。做到和現有代碼解耦,代碼也更容易理解了。對於大量if/else的情況也是類似來處理。