程序员潇然 发表于 2022-8-2 16:07:31

策略模式 Strategy 政策Policy 行为型 设计模式(二十五)

策略模式 Strategy

!(data/attachment/forum/202208/02/160436a2covk2zx22kpvpo.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

!(data/attachment/forum/202208/02/160448gigehw68uuqauqc7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")


与策略相关的常见词汇有:营销策略、折扣策略、教学策略、记忆策略、学习策略....

“策略”意味着分情况讨论,而不是一概而论

面对不同年龄段的人,面对不同的商品,必然将会有不同的话术;

面对购物总价的范围,很可能会有不同的折扣方案;

面对理解能力不同的学生,必然有不同的教学策略;

而在我们程序的世界里,“策略”就是分情况讨论。也就是**类似状态模式中的条件分支或者选择分支**。

只不过**状态模式中是事物的不同状态,而策略模式中关注的是处理方法**。

比如

```java
if(totalPrice > 1000){
//9折
else if(totalPrice > 2000){
//8折
}else if(totalPrice > 3000){
//7折
}
```



这就是一种打折策略,对应于购物总金额的不同,采用不同的处理方法。

显然,使用条件分支或者选择语句,类似状态模式中的分析,也存在类似的问题

如果条件过多,会导致**处理逻辑复杂**

而且,策略的逻辑与业务逻辑**耦合**在一起,如果处理方法变化还需要修改业务逻辑方法,**扩展性差**

而且,也**不适合增加新的策略方案**



### 意图

**定义一系列的算法,把他们一个个的封装起来,并使他们可以互相转换,本模式使得算法可以独立于使用它的客户端而变化。**

**别名:政策Policy**

策略模式与状态模式本质一样,只不过一个是状态,一个是行为算法。

### 结构

!(data/attachment/forum/202208/02/160520u363sfgllg30fh10.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")



**抽象策略角色Strategy**

定义了抽象的策略,比如打折,排序等

定义了策略的一致性访问接口,比如定义了一个排序接口 sort()

**具体策略角色ConcreteStrategy**

实现抽象策略的定义的接口,实现自己的行为算法,比如ConcreteStrategyA冒泡 ConcreteStrategyB快排

**环境类Context**

维护Strategy,持有一个Strategy的引用,用来管理Strategy,可以切换策略

是Strategy的使用者


### 代码示例

排序接口,定义了一个sort方法

```java
package strategy;
public interface SortStrategy {
void sort();
}
```

```java
package strategy;
public class Bubble implements SortStrategy {
    @Override
    public void sort() {
      System.out.println("冒泡排序,输出结果...");
    }
}
```

```java
package strategy;
public class QuickSort implements SortStrategy {
    @Override
    public void sort() {
      System.out.println("快速排序,输出结果...");
    }
}
```


环境类

内部持有一个SortStrategy,简单起见初始化为Bubble

使用一个简单的方法进行切换

并且提供sort方法,代理strategy的sort方法

```java
package strategy;
public class Context {
    private SortStrategy strategy = new Bubble();
    public void setStrategy(String strategy) {
      if(strategy.equals("bubble")){
            this.strategy = new Bubble();
      }else if(strategy.equals("quick")){
            this.strategy = new QuickSort();
      }
    }
    public void sort() {
      strategy.sort();
    }
}
```


测试方法

```java
package strategy;
public class Test {
public static void main(String[] args) {
    Context context = new Context();
    context.sort();
    context.setStrategy("quick");
    context.sort();
    context.setStrategy("bubble");
    context.sort();
    }
}
```

!(data/attachment/forum/202208/02/160700l20yphzhfexlppzd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")


上面的代码可以看得出来,具体的算法行为,被封装在了具体的策略类中,比如Bubble和QuickSort

通过环境类Context对算法进行管理切换。

本文作者:程序员潇然 疯狂的字节X https://crazybytex.com/


### 总结

**策略模式与状态模式是类似的,借助于多态的特性,以达到不同状态不同行为**

不同的场景使用不同的算法,这本就是一种“不同状态,不同行为”的含义延伸

**都是借助于多态特性,进而也就是依赖倒置原则---面向抽象编程,其根本也是为了“低耦合**”。

策略模式中使用独立的类来封装不同的算法行为,每一个类封装具体的行为

策略模式主要是将**算法的定义与使用进行分开**,算法被封装在不同的策略类中

借助于算法的环境类Context,针对抽象策略进行编程,符合依赖倒置原则

而且,新增加具体的算法,只需要增加一个新的具体的策略类即可。

策略模式将算法的定义与使用分开,具体的策略完全可以通过配置文件等方式注入到Context中,客户端完全不需要关注具体的策略

而且,**运行时可以随时的更换策略**

策略模式的Context,我们的示例中一个Context一个当前策略,那么Context到底内部维护几个策略?到底谁负责切换,是客户端还是Context

个人认为都是灵活的,策略模式的核心就在于算法的定义与使用的解耦,在接下来的其他事情,自己看情况随便来(随便的前提是合理有效)

只要是涉及到**多种算法行为**的

**切换**:策略可以运行时切换

**复用**:算法与使用解耦,算法可以单独扩展

**封装**:屏蔽使用者对算法内部数据结构等逻辑的了解,否则如果算法的实现耦合在客户端,客户端不是一清二楚么

都**可以考虑策略模式**,策略模式能够灵活的切换算法,以及算法独立发展,符合开闭原则

但是类似状态模式,策略模式也会产生很多小的具体的策略类,增加类的个数和运行时对象的个数。

!(data/attachment/forum/202206/16/141330jha7st9soow8772i.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "common_log.png")
`转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-124-1-1.html `
页: [1]
查看完整版本: 策略模式 Strategy 政策Policy 行为型 设计模式(二十五)