如何優(yōu)雅地處理switch-case

使用注解和多態(tài)。

思路:將自定義注解打在相應(yīng)的處理器上,在Service類初始化時(shí),自動(dòng)掃描打了響應(yīng)注解的處理器類,并保存下來,然后通過具體的傳參取出具體的類來處理。

具體看這個(gè)例子,現(xiàn)有一批資源Pojo類,資源Pojo主要有2個(gè)屬性,主鍵resourceId和資源類型resourceType,現(xiàn)要根據(jù)不同的資源類型用resourceId去查不同的接口,返回資源的詳細(xì)信息,返回的信息都是每個(gè)資源都會(huì)有的,比如資源名稱。

資源Pojo的定義是:

class ResourcePojo{
    private Long resourceId;
    private EnumResource resourceType;
}

再來定義一個(gè)查詢資源接口:

interface IResourceInfoGetter{
    //根據(jù)單個(gè)資源查詢
    ResourceModel getResourceInfo(ResourcePojo resource);
    //根據(jù)多個(gè)資源查詢
    List<ResourceModel> getResourceInfoList(List<ResourcePojo> resources);
}

class ResourceModel{
    private Long resourceId;
    private Integer resourceType;
    //這里為了簡潔就只寫個(gè)資源名稱,但其實(shí)可能還有更多的資源信息。
    private String resourceName;
}

/**
* 枚舉中有4個(gè)值的資源類型,分別表示機(jī)票、汽車票、長途汽車票、火車票的資源
*/
enum EnumResource{
    FLIGHT,BUS, LONG_DISTANCE_BUS,TRAIN;
}

現(xiàn)在可以開始寫代碼了,這里還有要注意的東西就是BUS,LONG_DISTANCE_BUS這兩種雖然是不同資源,但是查詢的接口是同一個(gè),所以雖然枚舉值有4個(gè),但是外部接口其實(shí)只有3個(gè)。

//新增注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@interface ResourceType {
    EnumResource type();
}

//把注解打到對(duì)應(yīng)的類上
@ResourceType(type = EnumResource.FLIGHT)
public class FlightResourceInfoGetter implements IResourceInfoGetter {
       ...
}

//service類
@Service
public class ResourceInfoGetter implements IResourceInfoGetter {
    private final static Map<EnumResource, IResourceInfoGetter> GETTER_STORE = new EnumMap<>(EnumResource.class);

    //有Getter所在包的包名
    private final static String PACKAGE_NAME = "xxx";
    //自動(dòng)掃描帶有自定義注解的類
    @PostConstruct
    private void init() {
        //需要引入第三方j(luò)ar包 org.reflections
        Reflections reflections = new Reflections(PACKAGE_NAME);
        //獲取包下所有IResourceInfoGetter
        Set<Class<? extends IResourceInfoGetter>> classes = reflections.getSubTypesOf(IResourceInfoGetter.class);
        for (Class<? extends IResourceInfoGetter> clazz : classes) {
            //因?yàn)閷?duì)象是被spring管理的,所以需要通過applicationContext拿bean。
            //為了解耦A(yù)pplicationContext和該類關(guān)系,使用了一個(gè)SpringContextHolder類。
            GETTER_STORE.put(clazz.getAnnotation(ResourceType.class).type(), SpringContextHolder.getBean(clazz));
        }
    }
    //根據(jù)不同的resources調(diào)用不同接口取出信息
    public List<ResourceModel> getResourceInfoList(List<ResourcePojo> resources){
        Map<IResourceInfoGetter, List<ResourcePojo>> getterMap = resources.stream().collect(Collectors.groupingBy(r -> GETTER_STORE.get(r.getResourceType())));
        List<ResourceModel> result = new ArrayList<>(resources.size());
        for (Map.Entry<IResourceInfoGetter, List<ResourcePojo>> entry : getterMap.entrySet()) {
            result.addAll(entry.getKey().getResourceInfoList(entry.getValue()));
        }
        return result;
    }
}


現(xiàn)在再來看如果新增一種resourceType,需要改動(dòng)哪些地方:

1.Enum類新增一種資源類型。
2.新增一個(gè)實(shí)現(xiàn)IResourceInfoGetter的類 (類上的注解 ),用來查詢第五種資源。

代碼比switch-case簡潔,擴(kuò)展性也比switch-case強(qiáng)。

總結(jié):利用多態(tài)和注解來替代switch-case代碼塊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容