策略模式

一、什么是策略模式

用不同的算法(方式)去解决同一个问题,并各个算法间得到替换,其主要目的是通过定义相似的算法,替换if-else写法。

二、策略模式组成角色

2.1 抽象策略(Strategy)类


2.2 具体策略(Concrete Strategy)类


2.3 环境(Context)类

三、策略模式应用(消除if-else)

策略模式的简单应用
我们先看一段代码,看代码之前回想下我前面说的三个角色,把这三个角色代入到代码中,思考这三个角色中在代码的作用

public class StrategyPattern {
    public static void main(String[] args) {
        Context c = new Context();
        Strategy s = new ConcreteStrategyA();
        c.setStrategy(s);
        c.strategyMethod();
        System.out.println("-----------------");
        s = new ConcreteStrategyB();
        c.setStrategy(s);
        c.strategyMethod();
    }
}
//抽象策略类
interface Strategy {
    public void strategyMethod();    //策略方法
}
//具体策略类A
class ConcreteStrategyA implements Strategy {
    public void strategyMethod() {
        System.out.println("具体策略A的策略方法被访问!");
    }
}
//具体策略类B
class ConcreteStrategyB implements Strategy {
    public void strategyMethod() {
        System.out.println("具体策略B的策略方法被访问!");
    }
}
//环境类
class Context {
    private Strategy strategy;
    public Strategy getStrategy() {
        return strategy;
    }
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
    public void strategyMethod() {
        strategy.strategyMethod();
    }
}

大白话:其实说的就是有一个接口(抽象接口),他有2个实现类A和B(具体策略)。然后有一个环境类Context。这个接口是Context的成员变量,然后根据外在环境来选择是用A和B。

仔细想想,这种设计思想,是不是跟if else语句非常的像!,也是根据条件来选择,执行哪种具体策略。

我们来试试用策略模式改写if else

传统if else

    if{
        // 逻辑1
        ......
    } else {
        // 逻辑2
        ......
    }

用策略模式改写

Context c = new Context();
    if(conditions){
        // 逻辑1
        Strategy s = new ConcreteStrategyA();
        c.setStrategy(s);
        c.strategyMethod();
    } else {
        // 逻辑2
        Strategy s = new ConcreteStrategyB();
        c.setStrategy(s);
        c.strategyMethod();
    }
}

emmm。优化了,但还没完全优化,这种写法依然还没脱离if else结构。

小结一下,即使用了策略模式,你该写的业务逻辑照常写,到逻辑分派的时候,还是变相的if else。而它的优化点是抽象了出了接口,将业务逻辑封装成一个一个的实现类,任意地替换。在复杂场景(业务逻辑较多)时比直接 if else 来的好维护些。

四、如何对策略模式进行优化

大家仔细想想,针对上述写法其实有2个痛点
1.具体策略类会过多
2.还无法彻底消除if else

第一个问题我们其实可以这样解决,把抽象策略和具体策略放在一个枚举类里

public enum Strategy {
    A{

        @Override
        public void exe() {
            System.out.println("执行具体策略A");
        }

    },
    B{
        @Override
        public  void exe() {
            System.out.println("执行具体策略B");
        }

    };

    public abstract void exe();

}

方法 exe() 相当于抽象策略,而A和B就相当于实现了抽象策略的具体策略
这样就只需要一个枚举类就可以解决具体策略类过多的问题,完美地解决了痛点~

再来看第二个痛点。彻底消除if else。
对了!直接用Map不就行了吗,Map<条件,具体策略>
预先put进去条件,需要的时候get不就行了吗

所以,解决之道就是 枚举类+Map
完整代码如下

public enum Strategy {
    A{

        @Override
        public void exe() {
            System.out.println("执行具体策略A");
        }

    },
    B{
        @Override
        public  void exe() {
            System.out.println("执行具体策略B");
        }

    };

    public abstract void exe();

}
public class Test {
    public static void main(String[] args) {
        Map<String, Strategy> map=new LinkedHashMap<>();
        map.put("A",Strategy.A);
        map.put("B",Strategy.B);

        String str="A";
        map.get(str).exe();
    }

}

这样的话即没有过多的具体策略类,也完全消除了if else

总结
写代码时总会出很多的if…else,或者case。如果在一个条件语句中又包含了多个条件语句就会使得代码变得臃肿,维护的成本也会加大,而策略模式就能较好的解决这个问题

先介绍了下策略模式,讲明了应用场景和优缺点,引出了策略模式的三大角色:
抽象策略;具体策略;环境
然后讲解了下策略模式的应用,普通写法还无法完全消除if else。
优化→枚举类+Map
来解决策略模式,具体策略类过多和无法完全消除if else的痛点。

                        
参考:https://blog.csdn.net/bookssea/article/details/117043820

相关推荐

  1. ·策略模式

    2024-06-15 10:28:08       35 阅读
  2. 策略模式

    2024-06-15 10:28:08       17 阅读
  3. 设计模式——策略模式

    2024-06-15 10:28:08       30 阅读
  4. 设计模式-策略模式

    2024-06-15 10:28:08       38 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-15 10:28:08       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-15 10:28:08       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-15 10:28:08       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-15 10:28:08       20 阅读

热门阅读

  1. B树与B+树与Mysql innodb的B+树和其相关索引

    2024-06-15 10:28:08       8 阅读
  2. 【AI开发】LangGraph基础

    2024-06-15 10:28:08       8 阅读
  3. mmyolo尝试

    2024-06-15 10:28:08       7 阅读
  4. linux shell实现端口查询

    2024-06-15 10:28:08       5 阅读
  5. std::vector的emplace_back 与 push_back 比较

    2024-06-15 10:28:08       11 阅读
  6. 数据结构 ->反转链表

    2024-06-15 10:28:08       10 阅读
  7. 程序员该有怎么样的职业素养

    2024-06-15 10:28:08       8 阅读
  8. 高等数学与初等数学的分水岭是什么?

    2024-06-15 10:28:08       8 阅读
  9. EventBus之Reactor实战

    2024-06-15 10:28:08       5 阅读
  10. 蓝色格调qss

    2024-06-15 10:28:08       6 阅读
  11. 185. 部门工资前三高的所有员工

    2024-06-15 10:28:08       8 阅读