策略模式+工廠模式取代if{}else{}

chillymint發表於2024-04-03

1. 策略+工廠實現相同業務抽象

策略模式:一種解耦的方法,它對演算法進行封裝,使得演算法的呼叫和演算法本身分離。使用策略模式客戶端程式碼不需要調整,演算法之間可以互相替換,因為不同的演算法實現的是同一個介面。策略模式是一種物件行為型模式。策略模式符合“開閉原則”。

1.1 定義策略介面

將成員的業務方法抽象為統一的策略介面。其中 InitializingBean 介面來自Spring框架,用於實現環境的統一工廠。

public interface SubjectTypeHandler {
	/**
	 * 列舉身份的識別
	 */
	SubjectInfoTypeEnum getHandlerType();

	/**
	 * 實際的題目的插入
	 */
	void add(SubjectInfoBO subjectInfoBO);

	/**
	 * 實際的題目的查詢
	 */
	SubjectOptionBO query(int subjectId);
}

1.2 實現策略工廠

此處的工廠即策略模式下的 “環境類” 要素,功能為根據不同的name找到其對應的不同的策略實現,實現方法為將實現NameHandler介面的類都裝載到strategyMap裡,除使用工廠實現外,也可以使用列舉+代理實現。

@Component
public class SubjectTypeHandlerFactory implements InitializingBean {
    @Resource
    private List<SubjectTypeHandler> subjectTypeHandlerList;

    private Map<SubjectInfoTypeEnum, SubjectTypeHandler> handlerMap = new HashMap<>();
    public SubjectTypeHandler getHandler(int subjectType){
        SubjectInfoTypeEnum byCode = SubjectInfoTypeEnum.getByCode(subjectType);
        return handlerMap.get(byCode);
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        for (SubjectTypeHandler subjectTypeHandler : subjectTypeHandlerList) {
            handlerMap.put(subjectTypeHandler.getHandlerType(), subjectTypeHandler);
        }
    }
}

1.3 為各成員實現各自的具體策略實現類

將各自的不同實現類宣告為元件(用於維護工廠),org.springframework.beans.factory.InitializingBean#afterPropertiesSet內部實現工廠註冊。

/**
 * 單選題目的策略類
 *
 */
@Component
public class RadioTypeHandler implements SubjectTypeHandler {

    @Resource
    private SubjectRadioService subjectRadioService;

    @Override
    public SubjectInfoTypeEnum getHandlerType() {
        return SubjectInfoTypeEnum.RADIO;
    }

    @Override
    public void add(SubjectInfoBO subjectInfoBO) {
        //單選題目的插入
        List<SubjectRadio> subjectRadioList = new LinkedList<>();
        subjectInfoBO.getOptionList().forEach(option -> {
            SubjectRadio subjectRadio = RadioSubjectConverter.INSTANCE.convertBoToEntity(option);
            subjectRadio.setSubjectId(subjectInfoBO.getId());
            subjectRadio.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            subjectRadioList.add(subjectRadio);
        });
        subjectRadioService.batchInsert(subjectRadioList);
    }

    @Override
    public SubjectOptionBO query(int subjectId) {
        SubjectRadio subjectRadio = new SubjectRadio();
        subjectRadio.setSubjectId(Long.valueOf(subjectId));
        List<SubjectRadio> result = subjectRadioService.queryByCondition(subjectRadio);
        List<SubjectAnswerBO> subjectAnswerBOList = RadioSubjectConverter.INSTANCE.convertEntityToBoList(result);
        SubjectOptionBO subjectOptionBO = new SubjectOptionBO();
        subjectOptionBO.setOptionList(subjectAnswerBOList);
        return subjectOptionBO;
    }

}
public class MultipleTypeHandler implements SubjectTypeHandler

......

經過改造,後面如果新增成員或者新功能實現,新增策略實現即可。這種改造符合開閉原則,適用較為複雜的邏輯判斷。

相關文章