type
status
date
slug
summary
tags
category
icon
password
意图
定义了算法家族,把他们分别封装起来使其可以相互替换。此模式让算法的变化不会影响到使用算法的用户。
它的优点是:
- 策略类之间可以自由切换:由于策略类都实现同一个接口,所以使它们之间可以自由切换。
- 易于扩展:增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“
- 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。
缺点是:
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
类图
策略模式的主要角色如下:
- 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口
- 具体策略(ConcreteStrategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为
- 环境(Context)类:持有一个策略类的引用,最终给客户端调用,环境类组合了策略接口并在初始化时就实例化了策略对象
实战案例
使用场景
- 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
- 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
- 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
- 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。
与简单工厂模式的区别
简单工厂模式可以做到的事情,策略模式都可以做到。策略模式可以做到的事情,简单工厂模式也可以做到,只是会变得麻烦。简单工厂模式没有组合接口,它主要是返回的接口实现类的实例化对象,最后调用的是接口实现类中的方法,而策略模式组合了接口,在初始化的时候已经创建好策略实例了,利用聚合的 Strategy 属性我们可以在策略模式中随意的拼接重写方法,而简单工厂模式是不管方法的拼接这些的,只关注最后的结果,不注重过程,而策略模式注重的是过程。
小结
设计模式要干的事情就是解耦。创建型模式是将创建和使用代码解耦,具体到工厂模式是解耦对象的创建和使用;结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦,具体到观察者模式是将观察者和被观察者代码解耦。策略模式也能起到解耦的作用,不过,它解耦的是策略的定义、创建、使用这三部分。实际上,一个完整的策略模式就是由这三个部分组成的。
- 策略类的定义比较简单,包含一个策略接口和一组实现这个接口的策略类。
- 策略的创建由工厂类来完成,封装策略创建的细节。
- 策略模式包含一组策略可选,客户端代码如何选择使用哪个策略,有两种确定方法:编译时静态确定和运行时动态确定。其中,“运行时动态确定”才是策略模式最典型的应用场景。
除此之外,我们还可以通过策略模式来移除 if-else 分支判断。实际上,这得益于策略工厂类,更本质上点讲,是借助“查表法”,根据 type 查表替代根据 type 分支判断。