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


前言

策略模式是设计模式里面比较简单的设计模式,其特点简单又实用,是我最喜欢的模式之一。当初学策略模式是因为听说策略模式可以用来消除 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的痛点。

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

  • 84
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
责任链设计模式是一种行为型设计模式,用于将请求的发送者和接收者解耦,使多个对象都有机会处理该请求。该模式将这些对象串成链,并沿着这条链传递请求,直到有一个对象能够处理它为止。 责任链模式的核心是定义一个处理请求的抽象类或接口,然后让多个具体的处理者对象继承或实现这个类/接口。每个具体的处理者对象都包含一个对下一个处理者对象的引用,形成一个链式结构。 当一个请求进入责任链时,责任链中的每个处理者都有机会处理该请求。如果可以处理请求,则进行处理;如果不能处理,则将请求传递给下一个处理者,直到有一个处理者能够处理它。 责任链模式的关键点是要找到合适的处理者顺序和条件。通常情况下,责任链模式适用于以下情况: 1. 有多个对象可以处理同一类型的请求,但具体由哪个对象来处理由运行时决定。 2. 不明确请求的接收者,希望请求在一个对象链中流动,直到被处理。 3. 需要动态地指定可以处理请求的对象集合。 使用责任链模式可以实现请求发送者和接收者的解耦,增加代码的灵活性和可扩展性。但同时也需要注意责任链的长度和效率问题,避免责任链过长或造成性能问题。 总结一下,责任链设计模式是一种将请求发送者和接收者解耦的设计模式,通过将多个处理者对象串成链,沿着这条链传递请求,直到有一个处理者能够处理它。这样可以增加代码的灵活性和可扩展性,适用于有多个对象可以处理同一类型请求的情况。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农BookSea

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值