更新時(shí)間:2018年12月07日11時(shí)48分 來(lái)源:傳智播客 瀏覽次數(shù):
---
typora-root-url: pic
---
# 設(shè)計(jì)模式之策略模式
## 概述
? 策略模式是指有一定行動(dòng)內(nèi)容的相對(duì)穩(wěn)定的策略名稱(chēng)。策略模式在古代中又稱(chēng)“計(jì)策”,簡(jiǎn)稱(chēng)“計(jì)”,如《漢書(shū)·高帝紀(jì)上》:“漢王從其計(jì)”。這里的“計(jì)”指的就是計(jì)謀、策略。策略模式就針對(duì)不同的情況使用不同的方法。簡(jiǎn)單點(diǎn)講,像我們寫(xiě)代碼時(shí)總會(huì)出很多的if…else,或者case,如果在一個(gè)條件語(yǔ)句中又包含了多個(gè)條件語(yǔ)句就會(huì)使得代碼變得臃腫,維護(hù)的成本也會(huì)加大,而策略模式就能較好的解決這個(gè)問(wèn)題。
## 重要的角色
1. 抽象策略(Strategy)角色,這是一個(gè)抽象角色,通常由一個(gè)接口或抽象類(lèi)實(shí)現(xiàn)。定義了所有的具體策略類(lèi)所需要實(shí)現(xiàn)的方法
2. 具體策略(ConcreteStrategy)角色:實(shí)現(xiàn)了相關(guān)的算法或行為。
3. 環(huán)境(Context)角色:持有一個(gè)Strategy的引用。
## 應(yīng)用場(chǎng)景
* 針對(duì)同一類(lèi)型問(wèn)題的多種處理方式,僅僅是具體行為或算法差別時(shí)。
* 需要安全地封裝多種同一類(lèi)型的操作,同時(shí)又達(dá)到解藕的效果
* 出現(xiàn)同一抽象類(lèi)有多個(gè)子類(lèi),而又需要使用 if-else 或者 switch-case 來(lái)選擇具體子類(lèi)時(shí)。
## 策略模式結(jié)構(gòu)圖
![1](1.png)
### 說(shuō)明
* Strategy是一個(gè)接口,定義了了具體實(shí)現(xiàn)類(lèi)需要實(shí)現(xiàn)的方法
* ConcreteStrategyA、ConcreteStrategyB、ConcreteStrategyC 都實(shí)現(xiàn)了Strategy接口
* Context 是一個(gè)環(huán)境類(lèi),用于調(diào)動(dòng)不同策略
## 舉例
? 商家的活動(dòng):針對(duì)不同節(jié)假日,商家總會(huì)對(duì)他們的商品做各種優(yōu)惠活動(dòng),比如,有打折,有贈(zèng)送,還滿減,優(yōu)惠券等,也有一些商品不參與活動(dòng),那么計(jì)算價(jià)格時(shí)就應(yīng)該保留原價(jià)。
## 分析
? 這里我們可以把打折、贈(zèng)送、滿減、優(yōu)惠券等的這些活動(dòng)看成是一個(gè)個(gè)具體的策略類(lèi),商家的活動(dòng)就是環(huán)境Context,商家舉行活動(dòng)就會(huì)調(diào)用不同的策略。從此之后,無(wú)論商家增加多少活動(dòng)、改變活動(dòng),我們只需增加實(shí)現(xiàn)類(lèi)便可。
## 代碼實(shí)現(xiàn)
### 1. 創(chuàng)建普通java工程
? ![2](2.png)
### 2. IStrategy
```java
/**
* 策略接口
*/
public interface IStrategy {
/**
* 不同策略共有的方法
*/
void strategy();
}
```
### 3. Gif 贈(zèng)送策略
```java
/**
* 贈(zèng)送策略
*/
public class Gif implements IStrategy {
@Override
public void strategy() {
System.out.println("買(mǎi)三送一");
}
}
```
### 4. FullReduction 滿減策略
```java
/**
* 滿減策略
* 滿100減30元
*/
public class FullReduction implements IStrategy {
public void strategy() {
System.out.println("滿100減30元");
}
}
```
### 5. Discount 折扣策略
```java
/**
* 打折策略
*/
public class Discount implements IStrategy {
@Override
public void strategy() {
System.out.println("8折優(yōu)惠,機(jī)不可失,失不再來(lái)");
}
}
```
### 6. Context 商家活動(dòng)類(lèi)
```java
/**
* 環(huán)境類(lèi),即商家
*/
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,"情人節(jié)玫瑰花大促銷(xiāo):");
context.callStrategy();
System.out.println();
context = new Context(reduction,"中秋節(jié)月餅大促銷(xiāo):");
context.callStrategy();
System.out.println();
context = new Context(dis,"國(guó)際節(jié)家電大促銷(xiāo):");
context.callStrategy();
System.out.println();
}
}
```
### 7. 運(yùn)行結(jié)果
? ![3](3.png)
## 總結(jié)
* 策略模式的優(yōu)點(diǎn):
* 提供了管理相關(guān)算法足的辦法。
* 避免了難以維護(hù)的多重條件選擇語(yǔ)句的使用。
* 提供了可以代替繼承關(guān)系的辦法。
* 策略模式的缺點(diǎn):
* 客戶端必須提前知道所有的策略類(lèi),并且自己決定使用那一個(gè)策略類(lèi)。
* 策略模式造成很多的策略類(lèi)。
北京校區(qū)