更新时间:2018年12月07日11时48分 来源:传智播客 浏览次数:
---
typora-root-url: pic
---
# 设计模式之策略模式
## 概述
策略模式是指有一定行动内容的相对稳定的策略名称。策略模式在古代中又称“计策”,简称“计”,如《汉书·高帝纪上》:“汉王从其计”。这里的“计”指的就是计谋、策略。策略模式就针对不同的情况使用不同的方法。简单点讲,像我们写代码时总会出很多的if…else,或者case,如果在一个条件语句中又包含了多个条件语句就会使得代码变得臃肿,维护的成本也会加大,而策略模式就能较好的解决这个问题。
## 重要的角色
1. 抽象策略(Strategy)角色,这是一个抽象角色,通常由一个接口或抽象类实现。定义了所有的具体策略类所需要实现的方法
2. 具体策略(ConcreteStrategy)角色:实现了相关的算法或行为。
3. 环境(Context)角色:持有一个Strategy的引用。
## 应用场景
* 针对同一类型问题的多种处理方式,仅仅是具体行为或算法差别时。
* 需要安全地封装多种同一类型的操作,同时又达到解藕的效果
* 出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。
## 策略模式结构图
![1](1.png)
### 说明
* Strategy是一个接口,定义了了具体实现类需要实现的方法
* ConcreteStrategyA、ConcreteStrategyB、ConcreteStrategyC 都实现了Strategy接口
* Context 是一个环境类,用于调动不同策略
## 举例
商家的活动:针对不同节假日,商家总会对他们的商品做各种优惠活动,比如,有打折,有赠送,还满减,优惠券等,也有一些商品不参与活动,那么计算价格时就应该保留原价。
## 分析
这里我们可以把打折、赠送、满减、优惠券等的这些活动看成是一个个具体的策略类,商家的活动就是环境Context,商家举行活动就会调用不同的策略。从此之后,无论商家增加多少活动、改变活动,我们只需增加实现类便可。
## 代码实现
### 1. 创建普通世博会现场工程
![2](2.png)
### 2. IStrategy
```世博会现场
/**
* 策略接口
*/
public interface IStrategy {
/**
* 不同策略共有的方法
*/
void strategy();
}
```
### 3. Gif 赠送策略
```世博会现场
/**
* 赠送策略
*/
public class Gif implements IStrategy {
@Override
public void strategy() {
System.out.println("买三送一");
}
}
```
### 4. FullReduction 满减策略
```世博会现场
/**
* 满减策略
* 满100减30元
*/
public class FullReduction implements IStrategy {
public void strategy() {
System.out.println("满100减30元");
}
}
```
### 5. Discount 折扣策略
```世博会现场
/**
* 打折策略
*/
public class Discount implements IStrategy {
@Override
public void strategy() {
System.out.println("8折优惠,机不可失,失不再来");
}
}
```
### 6. Context 商家活动类
```世博会现场
/**
* 环境类,即商家
*/
public class Context {
private String msg;
private IStrategy strategy;
public Context(IStrategy strategy, String msg){
this.strategy = strategy;
this.msg = msg;
}
public void callStrategy(){
System.out.println(this.msg);
strategy.strategy();
}
public static void main(String[] args) {
Discount dis = new Discount();
FullReduction reduction = new FullReduction();
Gif gif = new Gif();
Context context = new Context(gif,"情人节玫瑰花大促销:");
context.callStrategy();
System.out.println();
context = new Context(reduction,"中秋节月饼大促销:");
context.callStrategy();
System.out.println();
context = new Context(dis,"国际节家电大促销:");
context.callStrategy();
System.out.println();
}
}
```
### 7. 运行结果
![3](3.png)
## 总结
* 策略模式的优点:
* 提供了管理相关算法足的办法。
* 避免了难以维护的多重条件选择语句的使用。
* 提供了可以代替继承关系的办法。
* 策略模式的缺点:
* 客户端必须提前知道所有的策略类,并且自己决定使用那一个策略类。
* 策略模式造成很多的策略类。