如何使用 Spring 實(shí)現(xiàn)策略模式+工廠模式

一、策略模式

策略模式定義了一組算法,將每個(gè)算法都封裝起來(lái),并且使它們之間可以互換

1、策略模式主要角色

image.png

主要角色如下:

  • 封裝角色(Context): 也叫做上下文角色,起承上啟下封裝作用,屏蔽高層模塊對(duì)策略、算法的直接訪問,封裝可能存在的變化
  • 抽象策略角色(Strategy): 策略家族的抽象,通常為接口,定義每個(gè)策略或算法必須具有的方法和屬性
  • 具體策略角色(ConcreteStrategy): 實(shí)現(xiàn)抽象策略中的操作,該類含有具體的算法

2、實(shí)現(xiàn)策略模式

//抽象策略角色
public interface Strategy {
    //策略模式的運(yùn)算法則
    void doSomething();
}

//具體策略角色
public class ConcreteStrategy1 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具體策略1的運(yùn)算法則...");
    }
}

//具體策略角色
public class ConcreteStrategy2 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具體策略2的運(yùn)算法則...");
    }
}

public class Client {
    public static void main(String[] args) {
        //聲明一個(gè)具體的策略
        Strategy strategy = new ConcreteStrategy1();
        //聲明上下文對(duì)象
        Context context = new Context(strategy);
        //執(zhí)行封裝后的方法
        context.doAnything();
    }
}

執(zhí)行結(jié)果如下:

具體策略1的運(yùn)算法則...

二、使用Spring實(shí)現(xiàn)策略模式+工廠模式

1、實(shí)現(xiàn)策略類

public interface Strategy {
    //策略模式的運(yùn)算法則
    void doSomething();
}

@Component
public class ConcreteStrategy1 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具體策略1的運(yùn)算法則...");
    }

    @Override
    public String toString() {
        return "具體策略1";
    }
}

@Component
public class ConcreteStrategy2 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具體策略2的運(yùn)算法則...");
    }

    @Override
    public String toString() {
        return "具體策略2";
    }
}

@Component
public class DefaultStrategy implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("默認(rèn)策略的運(yùn)算法則...");
    }

    @Override
    public String toString() {
        return "默認(rèn)策略";
    }
}

2、實(shí)現(xiàn)工廠類

@Component
public class StrategyFactory {
    //Spring會(huì)自動(dòng)將Strategy接口的實(shí)現(xiàn)類注入到這個(gè)Map中,key為bean id,value值則為對(duì)應(yīng)的策略實(shí)現(xiàn)類
    @Autowired
    private Map<String, Strategy> strategyMap;

    public Strategy getBy(String strategyName) {
        return strategyMap.get(strategyName);
    }
}

Spring會(huì)自動(dòng)將Strategy接口的實(shí)現(xiàn)類注入到這個(gè)Map中(前提是實(shí)現(xiàn)類得是交給Spring 容器管理的),這個(gè)Map的key為bean id,可以用@Component(value = "xxx")的方式設(shè)置,如果直接用默認(rèn)的方式的話,就是首字母小寫。value值則為對(duì)應(yīng)的策略實(shí)現(xiàn)類

image.png

測(cè)試類:

@SpringBootTest
class SpringbootDemoApplicationTests {

    @Autowired
    private ApplicationContext context;

    @Test
    public void test() {
        context.getBean(StrategyFactory.class).getBy("concreteStrategy1").doSomething();
        context.getBean(StrategyFactory.class).getBy("concreteStrategy2").doSomething();
    }

}

執(zhí)行結(jié)果如下:

具體策略1的運(yùn)算法則...
具體策略2的運(yùn)算法則...

3、別名轉(zhuǎn)換

上面測(cè)試類調(diào)用的使用使用的bean id,實(shí)際業(yè)務(wù)中應(yīng)該是將傳入的code轉(zhuǎn)義成對(duì)應(yīng)的策略類的bean id

@Component
@PropertySource("classpath:application.properties")
@ConfigurationProperties(prefix = "strategy")
public class StrategyAliasConfig {
    private HashMap<String, String> aliasMap;

    public static final String DEFAULT_STATEGY_NAME = "defaultStrategy";

    public HashMap<String, String> getAliasMap() {
        return aliasMap;
    }

    public void setAliasMap(HashMap<String, String> aliasMap) {
        this.aliasMap = aliasMap;
    }

    public String of(String entNum) {
        return aliasMap.get(entNum);
    }
}

配置文件application.properties

strategy.aliasMap.strategy1=concreteStrategy1
strategy.aliasMap.strategy2=concreteStrategy2

@Component
public class StrategyFactory {
    @Autowired
    private StrategyAliasConfig strategyAliasConfig;

    //Spring會(huì)自動(dòng)將Strategy接口的實(shí)現(xiàn)類注入到這個(gè)Map中,key為bean id,value值則為對(duì)應(yīng)的策略實(shí)現(xiàn)類
    @Autowired
    private Map<String, Strategy> strategyMap;

    //找不到對(duì)應(yīng)的策略類,使用默認(rèn)的
    public Strategy getBy(String strategyName) {
        String name = strategyAliasConfig.of(strategyName);
        if (name == null) {
            return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME);
        }
        Strategy strategy = strategyMap.get(name);
        if (strategy == null) {
            return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME);
        }
        return strategy;

    }
}

測(cè)試類:

@SpringBootTest
class SpringbootDemoApplicationTests {

    @Autowired
    private ApplicationContext context;

    @Test
    public void test() {
        context.getBean(StrategyFactory.class).getBy("strategy1").doSomething();
        context.getBean(StrategyFactory.class).getBy("strategy2").doSomething();
    }

}

執(zhí)行結(jié)果如下:

具體策略1的運(yùn)算法則...
具體策略2的運(yùn)算法則...
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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