从零开始学设计模式(十六):策略模式(Strategy Pattern)

简介: 策略模式(Strategy Pattern)也被称为政策模式(Policy)。它指的是定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,算法的变化不会影响使用算法的客户。

定义


策略模式(Strategy Pattern)也被称为政策模式(Policy)。它指的是定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,算法的变化不会影响使用算法的客户。


策略模式通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。它属于对象行为模式。


可以这么理解:策略就是解决问题的办法。一个问题往往有很多种不同的解决办法,每一种办法就是一种策略了,就好比以前高中的时候解决数学问题,一个题目也可以有很多种解决办法,但是每个人都可以根据一定的因素或者条件来选择不同的策略解决问题。


组成部分


策略模式包含以下三个主要部分:


1、抽象策略类(Strategy):它主要定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。


2、具体策略类(Concrete Strategy):它主要就是继承了抽象策略类,并且提供具体的算法实现。


3、环境类(Context):也叫上下文,起承上启下封装作用,它持有一个策略类的引用,对策略进行二次封装,目的是屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。最终给客户端调用。


例子


上面的介绍完可能还是有点不太好理解,看一个简单的例子,就对策略模式有清晰的认识了。


首先定义一个抽象策略类,定义一个走路的抽象方法:


/**
 * @Author: 江夏
 * @Date: 2021/11/23/21:16
 * @Description:抽象策略类
 */
public abstract class Strategy {
    public abstract void run();
}
复制代码


接着定义两个具体的策略类继承抽象策略类,并且实现抽象的策略方法:


/**
 * @Author: 江夏
 * @Date: 2021/11/23/21:17
 * @Description:具体策略类1
 */
public class ConcreteStrategy1 extends Strategy {
    @Override
    public void run() {
        System.out.println("具体策略类ConcreteStrategy1跑着走");
    }
}
复制代码


/**
 * @Author: 江夏
 * @Date: 2021/11/23/21:17
 * @Description:具体策略类2
 */
public class ConcreteStrategy2 extends Strategy {
    @Override
    public void run() {
        System.out.println("具体策略类ConcreteStrategy2慢悠悠地走");
    }
}
复制代码


接着就是上下文context类:


/**
 * @Author: 江夏
 * @Date: 2021/11/23/21:18
 * @Description:上下文类
 */
public class Context {
    public Strategy strategy;
    //构造函数
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    public void process(){
        strategy.run();
    }
}
复制代码


最后再来一个测试方法:


/**
 * @Author: 江夏
 * @Date: 2021/11/23/21:20
 * @Description:测试方法
 */
public class StrategyPatternTest {
    public static void main(String[] args) {
        Context context = null;
        System.out.println("策略一");
        context = new Context(new ConcreteStrategy1());
        context.process();
        System.out.println("策略二");
        context = new Context(new ConcreteStrategy2());
        context.process();
    }
}
复制代码


运行结果如下:

f1acb86bba924791a25f7b0f170a6b34~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


看完了案例,可能会觉得这不是前一篇的模版方法模式吗?其实策略模式和模版方法模式很相似。


策略模式与模版方法模式的区别仅仅是多了一个单独的上下文类Context。在模版方法模式中,调用算法的主体在抽象的父类中,而在策略模式中,调用算法的主体则是封装到了上下文Context类中,抽象策略类只是为了定义规范,里面一般不包含逻辑。策略模式中加了上下文类,通过上下类调用方法,屏蔽了直接对具体实现的访问,更符合面向对象的原则。


策略模式的优点


1、策略类之间可以自由切换,由于策略类实现自同一个抽象,所以他们之间可以自由切换。


2、易于扩展,增加一个新的策略对策略模式来说非常容易,基本上可以在不改变原有代码的基础上进行扩展,只需要新增一个类就可以了。


策略模式的缺点


1、策略模式易于拓展的后果就是维护各个策略类会给开发带来额外开销,每一个策略都是一个类,复用的可能性很小、类数量增多。


2、所有的策略类都需要对外暴露,因为使用哪种策略是由客户端来决定的。违背了迪米特法则。


应用场景


策略模式实质上就是面向对象中的继承和多态,使用策略模式的场景很多,而且在很多应用的场景中,在策略模式中一般会看到模版方法模式的影子,所以策略模式的应用场景和模版方法基本差不多,比如:


1、如果代码中几个类的主要逻辑相同,只在部分逻辑的算法和行为上有一些区别;


2、有几种相似的逻辑,但是需要由客户端动态地决定使用哪一种;


总结


策略模式是一种简单并且常用的模式,它主要就一个算法抽象类或者接口封装算法、然后多个具体的算法实现类实现它的方法再被一个上下文类来包装一下。一般来说,策略模式不会单独使用,跟模版方法模式、工厂模式等混合使用的情况比较多。


本文以及之前的所有的设计模式中的例子代码,都将同步至github,需要的欢迎下载star!

目录
相关文章
|
17天前
|
设计模式 算法 PHP
php设计模式--策略模式(六)
php设计模式--策略模式(六)
11 0
|
3月前
|
设计模式 算法 搜索推荐
设计模式之策略模式
设计模式之策略模式
41 0
|
3月前
|
设计模式 算法 Java
行为型设计模式-策略模式(Strategy Pattern)
行为型设计模式-策略模式(Strategy Pattern)
|
3月前
|
设计模式 算法
设计模式 - 行为型模式_ 访问者模式Visitor Pattern
设计模式 - 行为型模式_ 访问者模式Visitor Pattern
39 1
设计模式 - 行为型模式_ 访问者模式Visitor Pattern
|
12天前
|
设计模式 存储 Java
Java设计模式:解释一下单例模式(Singleton Pattern)。
`Singleton Pattern`是Java中的创建型设计模式,确保类只有一个实例并提供全局访问点。它通过私有化构造函数,用静态方法返回唯一的实例。类内静态变量存储此实例,对外仅通过静态方法访问。
16 1
|
1月前
|
设计模式 算法
策略模式--设计模式
策略模式--设计模式
17 0
|
1月前
|
设计模式 算法 Java
【设计模式】策略模式
【设计模式】策略模式
|
3月前
|
设计模式 算法 自动驾驶
常见的设计模式(模板与方法,观察者模式,策略模式)
随着时间的推移,软件代码越来越庞大,随着而来的就是如何维护日趋庞大的软件系统。在面向对象开发出现之前,使用的是面向过程开发来设计大型的软件程序,面向过程开发将软件分成一个个单独的模块,模块之间使用函数进行组合,最后完成系统的开发,每次需要修改软件,如果不涉及好各个模块的关系,就会导致软件系统难以维护,从而导致软件变得不可使用。面向对象方法用对象模拟问题域中的实体,以对象间的联系刻画实体间联系
65 2
|
3月前
|
设计模式 算法
设计模式 | 策略模式
设计模式 | 策略模式
18 0
|
3月前
|
设计模式 算法 Go
Golang设计模式——15策略模式
Golang设计模式——15策略模式
28 0