如何使用 Spring 实现策略模式+工厂模式


prtyaa
prtyaa 2023-12-30 22:21:05 62151
分类专栏: 资讯

一、策略模式

策略模式定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换

1、策略模式主要角色

主要角色如下:

  • 封装角色(Context): 也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化
  • 抽象策略角色(Strategy): 策略家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性
  • 具体策略角色(ConcreteStrategy): 实现抽象策略中的操作,该类含有具体的算法

2、实现策略模式

//抽象策略角色
public interface Strategy {
    //策略模式的运算法则
    void doSomething();
}

//具体策略角色
public class ConcreteStrategy1 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具体策略1的运算法则...");
    }
}

//具体策略角色
public class ConcreteStrategy2 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具体策略2的运算法则...");
    }
}

public class Client {
    public static void main(String[] args) {
        //声明一个具体的策略
        Strategy strategy = new ConcreteStrategy1();
        //声明上下文对象
        Context context = new Context(strategy);
        //执行封装后的方法
        context.doAnything();
    }
}

执行结果如下:

具体策略1的运算法则...

二、使用Spring实现策略模式+工厂模式

1、实现策略类

public interface Strategy {
    //策略模式的运算法则
    void doSomething();
}

@Component
public class ConcreteStrategy1 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具体策略1的运算法则...");
    }

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

@Component
public class ConcreteStrategy2 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("具体策略2的运算法则...");
    }

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

@Component
public class DefaultStrategy implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("默认策略的运算法则...");
    }

    @Override
    public String toString() {
        return "默认策略";
    }
}

2、实现工厂类

@Component
public class StrategyFactory {
    //Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
    @Autowired
    private Map<String, Strategy> strategyMap;

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

Spring会自动将Strategy接口的实现类注入到这个Map中(前提是实现类得是交给Spring 容器管理的),这个Map的key为bean id,可以用@Component(value = "xxx")的方式设置,如果直接用默认的方式的话,就是首字母小写。value值则为对应的策略实现类

测试类:

@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();
    }

}

执行结果如下:

具体策略1的运算法则...
具体策略2的运算法则...

3、别名转换

上面测试类调用的使用使用的bean id,实际业务中应该是将传入的code转义成对应的策略类的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会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
    @Autowired
    private Map<String, Strategy> strategyMap;

    //找不到对应的策略类,使用默认的
    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;

    }
}

测试类:

@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();
    }

}

执行结果如下:

具体策略1的运算法则...
具体策略2的运算法则...

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=32808
赞同 0
评论 0 条
prtyaaL1
粉丝 1 发表 2554 + 关注 私信
上周热门
银河麒麟添加网络打印机时,出现“client-error-not-possible”错误提示  1504
银河麒麟打印带有图像的文档时出错  1423
银河麒麟添加打印机时,出现“server-error-internal-error”  1213
统信操作系统各版本介绍  1134
统信桌面专业版【如何查询系统安装时间】  1131
统信桌面专业版【全盘安装UOS系统】介绍  1086
麒麟系统也能完整体验微信啦!  1043
统信【启动盘制作工具】使用介绍  692
统信桌面专业版【一个U盘做多个系统启动盘】的方法  635
信刻全自动档案蓝光光盘检测一体机  542
本周热议
我的信创开放社区兼职赚钱历程 40
今天你签到了吗? 27
信创开放社区邀请他人注册的具体步骤如下 15
如何玩转信创开放社区—从小白进阶到专家 15
方德桌面操作系统 14
我有15积分有什么用? 13
用抖音玩法闯信创开放社区——用平台宣传企业产品服务 13
如何让你先人一步获得悬赏问题信息?(创作者必看) 12
2024中国信创产业发展大会暨中国信息科技创新与应用博览会 9
中央国家机关政府采购中心:应当将CPU、操作系统符合安全可靠测评要求纳入采购需求 8

添加我为好友,拉您入交流群!

请使用微信扫一扫!