【浅谈设计模式】(14): 策略模式--臣有上中下三策,可来一看?

本文介绍了策略模式的概念,通过古代战争的例子阐述了其作用,解决if-else复杂性。文章提供了入门案例,展示了如何创建抽象策略类、具体策略类和环境类,并通过测试类运行展示效果。此外,文章还结合工厂模式进一步优化,使得策略的创建更加灵活,减少了代码中的条件判断,提高了代码可读性和可扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

渔夫出海前 并不知道鱼在哪
但还是会选择出海,因为相信会满载而归,很多时间,选择了才有机会,相信了才有可能。大胆的迈出想走的那一步吧,只要一直奔赴在路上,就终究会看到一片只为你而盛开的花海。

一、入门

1.1 概述

策略模式在古代中又称“计策”,简称“计”,如《汉书·高帝纪上》:“汉王从其计”。

而在现代,类似于每次向领导汇报的方案 A、方案B、方案C 等,然后具体采用哪个,由领导自己定夺。

这就是策略模式,理解起来比较 easy 了。

策略模式:,它通过对算法进行封装,把使用算法的责任算法的实现分割开来,并委派给不同的对象对这些算法进行管理。。指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。

那它主要解决什么问题呢

以古代战争为例

  • 情况1:如果对方人数远小于我方,则兵戎相见

  • 情况2:如果对方人数与我方相当,则和平发展

  • 情况3:如果对方人数远大于我方,则俯首称臣

这时候对应代码就是:

if( enemy < me ){
   System.out.println("you are my son");
}else if(enemy == me){
    System.out.println("和平发展");
}else if(enemy > me) {
    System.out.println("you are my father");
}
复制代码

而使用策略模式,它能够解决,if else 所带来的复杂和难以维护,也就是一坨坨的 if-else 太多了太难看了,大佬发明了这种模式,让我们的代码能更优雅点。

1.2 结构

策略模式的主要角色如下:

  • 抽象策略类(Strategy):这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

  • 具体策略类(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。

  • 环境类(Context)类:持有一个策略类的引用,最终给客户端调用。

二、入门案例实战

对上面说的案例进行入门实战。

抽象策略类:

publicinterfaceMyStrategy {
    publicvoidsay();
}
复制代码

具体策略类:

publicclassStrategyAimplementsMyStrategy{
    @Override
    publicvoidsay() {
        System.out.println("you are my father !");
        System.out.println("=====");
    }
}

publicclassStrategyBimplementsMyStrategy{
    @Override
    publicvoidsay() {
        System.out.println("和平共处!");
        System.out.println("=====");
    }
}

publicclassStrategyCimplementsMyStrategy{
    @Override
    publicvoidsay() {
        System.out.println("you are my son !!!");
        System.out.println("=====");
    }
}
复制代码

环境类:

publicclassMyContext {
    private MyStrategy strategy;

    publicMyContext(MyStrategy strategy){
        this.strategy = strategy;
    }

    publicvoidexec(){
        strategy.say();
    }
}
复制代码

测试类:

publicclassTestClient {
    publicstaticvoidmain(String[] args) {
        System.out.println("遇到比我强的:");new MyContext(new StrategyA()).exec();
        System.out.println("遇到跟我一样的:");new MyContext(new StrategyB()).exec();
        System.out.println("遇到比我菜的:");new MyContext(new StrategyC()).exec();
    }
}
复制代码

输出结果:

三、工厂模式+策略模式实战

策略模式有个缺点,就是每次都需要 new 一个策略类来实现,可以结合工厂模式帮我们创建策略类,另外并未完全消除 if-else,使用工厂模式可以让代码变得更为清晰,只需根据传入的 code 调用工厂进行执行对应的策略即可。

策略接口

publicinterfaceMsgStrategy {
    voidsendMsg();
}
复制代码

值班消息

publicclassMsgOneimplementsMsgStrategy{

    @OverridepublicvoidsendMsg() {
        System.out.println("发送值班消息!");
    }
}
复制代码

如果是SpringBoot项目,策略类可以这样写,让策略类自动注册到工厂中,

工厂类里面就无需用静态代码库来生成策略产品

    /*
    @ServicepublicclassMsgOne implements Strategy, InitializingBean {
        @Overridepublic void sendMsg() {
            System.out.println("发送值班消息");
        }
        @Overridepublic void afterPropertiesSet() throws Exception {
            Factory.register(StrategyEnum.CONCRETESTRATEGY1.getStrategyName(), this);
        }
    }
    */
复制代码

消息变更通知

publicclassMsgThreeimplementsMsgStrategy{
    @OverridepublicvoidsendMsg() {
        System.out.println("发送消息变更提醒");
    }
}
复制代码

模板消息枚举类

/**
 * 模板消息枚举类
 * @Authorxiaolei
 * @Date 2023/2/17 10:28
 **/publicenumMsgEnum {
    MSG_STRATEGY_1(101,"值班提醒"),
    MSG_STRATEGY_2(201,"巡检提醒"),
    MSG_STRATEGY_3(301,"信息变更通知")
    ;
    privateInteger code;
    privateString msgType;
    MsgEnum(Integer code,String msgType){
        this.code = code;
        this.msgType = msgType;
    }
    publicIntegergetCode(){
        returnthis.code;
    }
    publicStringgetMsgType(){
        returnthis.msgType;
    }
}
复制代码

工厂类

public class MsgFactory {
    private static Map<Integer,MsgStrategy> factory = new ConcurrentHashMap<>();
    /**
     * 生产策略消息
     */
    static {
        factory.put(MsgEnum.MSG_STRATEGY_1.getCode(),new MsgOne());
        factory.put(MsgEnum.MSG_STRATEGY_2.getCode(),new MsgTow());
        factory.put(MsgEnum.MSG_STRATEGY_3.getCode(),new MsgThree());
    }

    /**
     * 根据类型获取策略
     */
    public static MsgStrategy getStrategy(Integer code){
        return factory.get(code);
    }

    public static void setStrategy(Integer code,MsgStrategy msgStrategy){
        factory.put(code,msgStrategy);
    }

}
复制代码

测试类

publicclassMainTest {
    publicstaticvoidmain(String[] args){
        int code = 101;
        MsgStrategy strategy = MsgFactory.getStrategy(code);
        strategy.sendMsg();
    }
}
复制代码

四、总结

优点

  • 策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换。

  • 易于扩展:增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合”开闭原则“

  • 避免使用多重条件选择语句,充分体现面向对象设计思想

🍔总结:在开发中,凡是有同类型类似的算法需求,可以尝试使用策略模式进行封装来应对不同的变化。

作者:潇雷

链接:https://juejin.cn/post/7203989487138144312

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值