SpringBoot中實現策略模式-減少if else


------------------------目錄-------------------------------------

一、策略模式概念

二、策略模式優缺點

三、借用springboot框架實現策略模式

四、常見的實現策略模式

------------------------------------------------------------------

一、策略模式概念

策略(Strategy)模式的定義:該模式定義了一系列算法,並將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬於對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,並委派給不同的對象對這些算法進行管理。

二、策略模式優缺點

策略模式的主要優點如下

  1. 多重條件語句不易維護,而使用策略模式可以避免使用多重條件語句。
  2. 策略模式提供了一系列的可供重用的算法族,恰當使用繼承可以把算法族的公共代碼轉移到父類里面,從而避免重復的代碼。
  3. 策略模式可以提供相同行為的不同實現,客戶可以根據不同時間或空間要求選擇不同的。
  4. 策略模式提供了對開閉原則的完美支持,可以在不修改原代碼的情況下,靈活增加新算法。
  5. 策略模式把算法的使用放到環境類中,而算法的實現移到具體策略類中,實現了二者的分離。

其主要缺點如下:

  1. 客戶端必須理解所有策略算法的區別,以便適時選擇恰當的算法類。
  2. 策略模式造成很多的策略類。

三、借用springboot框架實現策略模式

1、簡述

由於公司開發一個類似IM通訊系統的項目,所以用到了大量的自定義事件,根據事件驅動進行業務處理。使用到了策略模式對於開發的團隊成員來說只需要關注自己的業務實現即可,

有統一的處理入口,自動路由。

這里面有如下幾個重要的類

  AbstractHandler:抽象類,定義業務處理方法和處理業務的類型。

  ContextHandlerService:對外暴露的類,根據參數類型進行業務路由。

  EventEnum、HandlerParam、HandlerResult:通用類分別對應:事件定義、請求通用參數、結果返回。

  業務實現類:繼承AbstractHandler類重寫方法。

注:使用時候請注意ContextHandlerService類上的@Service和實現類上的@Componet注解,用於Spring掃描。

項目結構

2、源代碼如下:

AbstractHandler:抽象類。

package city.ablert.commont;

import java.util.List;

/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @date 2020/7/29  4:06 PM
 */
public abstract class AbstractHandler {


    /**
     * 業務處理實現抽象方法
     *
     * @param param
     * @return
     */
    public abstract HandlerResult strategy(HandlerParam param);


    /**
     * 返回業務類型,可以配置多個事件也可以是單個事件
     *
     * @return
     */
    public abstract List<EventEnum> eventTypes();
}
View Code

ContextHandlerService:對外暴露的類。

package city.ablert.service;

import city.ablert.commont.AbstractHandler;
import city.ablert.commont.EventEnum;
import city.ablert.commont.HandlerParam;
import city.ablert.commont.HandlerResult;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @date 2020/7/29  4:13 PM
 */
@Service
public class ContextHandlerService implements ApplicationContextAware {
    private static final Map<EventEnum, AbstractHandler> HANDLER_MAP = new HashMap<>();

    private ApplicationContext applicationContext;

    /**
     * 實現ApplicationContextAware接口獲取springboot容器對象
     * 方便創建完成對象后進行初始化
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }


    /**
     * @PostConstruct 聲明在創建完成對象並且注入屬性后執行改方法
     *
     *
     */
    @PostConstruct
    public void init() {
        //獲取AbstractHandler類的所有實現類
        Map<String, AbstractHandler> type = applicationContext.getBeansOfType(AbstractHandler.class);
        for (Map.Entry<String, AbstractHandler> entry : type.entrySet()) {
            //獲取單個實現類
            AbstractHandler value = entry.getValue();
            if (value.eventTypes() == null) {
                continue;
            }
            //或者注冊事件,並且循環全部注冊
            for (EventEnum eventEnum : value.eventTypes()) {
                HANDLER_MAP.put(eventEnum, value);
            }
        }
    }

    /**
     * 業務處理類的路由方法
     * @param param
     * @return
     */
    public HandlerResult strategy(HandlerParam param) {
        AbstractHandler handler = HANDLER_MAP.get(param.getEvent());
        if (handler == null) {
            return null;
        }
        return handler.strategy(param);
    }
}
View Code

EventEnum、HandlerParam、HandlerResult:事件定義、請求通用參數、結果返回。

package city.ablert.commont;

/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @date 2020/7/29  4:00 PM
 */
public enum EventEnum {
    ERROR("error", "異常中斷"),
    CLOSE("close", "正常關閉"),
    LOGIN("login", "登錄"),
    HEALTHY("healthy", "健康監測");

    private String value;

    private String desc;

    EventEnum(String value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    public String getValue() {
        return value;
    }

    public String getDesc() {
        return desc;
    }

    /**
     *
     * @param value
     * @return
     */
    public static EventEnum valueTo(String value) {
        EventEnum[] values = EventEnum.values();
        for (EventEnum anEnum : values) {
            if (anEnum.getValue().equals(value)) {
                return anEnum;
            }
        }
        return null;
    }
}
View Code
package city.ablert.commont;


/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @date 2020/7/29  4:10 PM
 */
public class HandlerParam<T> {

    public HandlerParam(EventEnum event) {
        this.event = event;
    }

    public HandlerParam(EventEnum event, T param) {
        this.event = event;
        this.param = param;
    }

    /**
     * 事件類型
     */
    private EventEnum event;

    /**
     * 請求業務參數泛型,對象
     */
    private T param;


    public EventEnum getEvent() {
        return event;
    }

    public void setEvent(EventEnum event) {
        this.event = event;
    }

    public T getParam() {
        return param;
    }

    public void setParam(T param) {
        this.param = param;
    }

    @Override
    public String toString() {
        return "HandlerParam{" +
                "event=" + event +
                ", param=" + param +
                '}';
    }
}
View Code
package city.ablert.commont;

/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @date 2020/7/29  4:09 PM
 */
public class HandlerResult<T> {

    /**
     * 構造方法
     */
    public HandlerResult() {
    }

    public HandlerResult(T result) {
        this.result = result;
    }

    /**
     * 返回結果泛型對象
     */
    private T result;


    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "HandlerResult{" +
                " result=" + result +
                '}';
    }
}
View Code

業務實現類:繼承AbstractHandler類(拓展其他類型直接繼承該類編寫業務即可,調用統一的入口,需要指定事件類型)。

package city.ablert.strategy;

import city.ablert.commont.AbstractHandler;
import city.ablert.commont.EventEnum;
import city.ablert.commont.HandlerParam;
import city.ablert.commont.HandlerResult;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @date 2020/7/29  4:26 PM
 */
@Component
public class LoginHandler extends AbstractHandler {

    @Override
    public HandlerResult strategy(HandlerParam param) {
        //根據參數進行業務處理
        System.out.println("業務處理");

        //返回結果
        return new HandlerResult<String>("業務處理完畢");
    }

    @Override
    public List<EventEnum> eventTypes() {
        return Arrays.asList(EventEnum.LOGIN, EventEnum.HEALTHY);
    }
}

業務測試類

package city.albert;

import city.ablert.Application;
import city.ablert.commont.EventEnum;
import city.ablert.commont.HandlerParam;
import city.ablert.commont.HandlerResult;
import city.ablert.service.ContextHandlerService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @date 2020/7/29  4:42 PM
 */
@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class StrategyTest {


    @Autowired
    private ContextHandlerService service;


    @Test
    public void test() {
        //定於路由參數即可
        HandlerParam<String> param = new HandlerParam<>(EventEnum.LOGIN, "我是參數");
        System.out.println("請求參數:" + param);
        HandlerResult result = service.strategy(param);
        System.out.println("返回結果" + result);

    }
}
View Code

運行結果

 

 

四、常見的實現策略模式

 

這里 ----> https://www.runoob.com/design-pattern/strategy-pattern.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM