前言

策略模式是设计模式里面比较简单的设计模式,其特点简单又实用,是我最喜欢的模式之一。当初学策略模式是因为听说策略模式可以用来消除 if else语句。
多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。
在这里插入图片描述


一、策略模式介绍

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

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

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

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

在这里插入图片描述

策略模式有三个组成角色:
抽象策略(Strategy)类
具体策略(Concrete Strategy)类
环境(Context)类

这三个角色贯穿策略模式的整个设计思想,大家要牢牢记住
在这里插入图片描述
策略模式有如下应用场景:
在这里插入图片描述

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

优点缺点
多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码策略模式造成很多的策略类,增加维护难度。
策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

二、策略模式应用(消除 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语句非常的像!,也是根据条件来选择,执行哪种具体策略。
在这里插入图片描述
不多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();
    }
}

在这里插入图片描述

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

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

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐