Java中利用反射(或spring)和多態來解決大量swich/case或者if/else的方法

背景

工作中經常會有一些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的情況也是類似來處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章