一文搞懂策略模式(优化策略模式完全消除if else)

简介: 一文搞懂策略模式(优化策略模式完全消除if else)

前言

策略模式是设计模式里面比较简单的设计模式,其特点简单又实用,是我最喜欢的模式之一。当初学策略模式是因为听说策略模式可以用来消除 if else语句。

多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。

一、策略模式介绍

在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或自己开私家车等,超市促销可以釆用打折、送商品、送积分等方法。

在软件开发中也常常遇到类似的情况,当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如数据排序策略有冒泡排序、选择排序、插入排序、二叉树排序等。


如果使用多重条件转移语句实现(即硬编码),不但使条件语句变得很复杂,而且增加、删除或更换算法要修改原代码,不易维护,违背开闭原则。如果采用策略模式就能很好解决该问题。


策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。


20210519203202934.png

策略模式有三个组成角色:

抽象策略(Strategy)类

具体策略(Concrete Strategy)类

环境(Context)类

这三个角色贯穿策略模式的整个设计思想,大家要牢牢记住

策略模式有如下应用场景:

策略模式的优点和缺点我直接用表格方式给大家列举:

image.png

二、策略模式应用(消除 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语句非常的像!,也是根据条件来选择,执行哪种具体策略。


20210519205141685.png

不多BB,我们来试试用策略模式改写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();
    }
}

20210519211313306.png

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的痛点。

以上就是本篇文章 关于 策略模式 的内容

骚等别划走,恰饭时间~

目录
相关文章
|
1月前
|
设计模式 算法 Java
二十三种设计模式全面解析-当你的代码需要多种算法时,策略模式是你的救星!
二十三种设计模式全面解析-当你的代码需要多种算法时,策略模式是你的救星!
|
8月前
|
设计模式 Java Apache
设计模式第九讲:常见重构技巧 - 去除不必要的!=
设计模式第九讲:常见重构技巧 - 去除不必要的!=
|
设计模式 Java
【Java设计模式 面向对象设计思想】五 多用组合少用继承编程
【Java设计模式 面向对象设计思想】五 多用组合少用继承编程
171 0
【Java设计模式 面向对象设计思想】五 多用组合少用继承编程
|
11月前
|
设计模式 算法 Java
优化代码复用与维护性:详解Java设计模式中的策略模式
优化代码复用与维护性:详解Java设计模式中的策略模式
|
设计模式
设计模式(7) -- 合成复用原则和七大原则总结
设计模式(7) -- 合成复用原则和七大原则总结
110 0
设计模式(7) -- 合成复用原则和七大原则总结
|
设计模式 uml
设计模式七大原则——合成复用原则
设计模式七大原则——合成复用原则
设计模式七大原则——合成复用原则
|
设计模式 算法 Java
如何优雅的用策略模式,取代臃肿的 if-else 嵌套,看这篇就够了
如何优雅的用策略模式,取代臃肿的 if-else 嵌套,看这篇就够了
964 0
如何优雅的用策略模式,取代臃肿的 if-else 嵌套,看这篇就够了
|
设计模式 算法 Java
用策略模式设计车子模型
小强所在的游戏公司最近设计了一款赛车游戏,游戏中会有很多种的车型,比如自行车、三轮车、小汽车、卡车、跑车等等。基于面向对象的设计思路,小强设计了一个车的超类,并让各种车辆继承这个超类。因为是新游戏,为了看看市场反响,所以第一版本所有类型的车辆只有样式不同,其他功能都一样:
用策略模式设计车子模型
|
Java Spring 容器
利用策略模式优化过多 if else 代码
利用策略模式优化过多 if else 代码
|
设计模式 安全 Python
设计模式中应遵循的基本原则
设计模式中应遵循的基本原则
189 0