---
# System prepended metadata

title: 虎年行大運 - Design Pattern - Strategy
tags: [Design Pattern]

---

# 虎年行大運 - Design Pattern - Strategy

## 前言
在生活中，一定都有遇過目的一樣，但過程總會有些許不同的事情。

以買菜這件事情而言，去傳統市場買？去零售超市買？去量販店買？都是買菜，但是過程卻可能不同。

傳統市場和零售超市可能在家附近，量販店可能就要驅車前往。而在價格部份則可能量販店較便宜。

類同上述目的相同、過程不同的事情百百種。程式設計也相同，若完成需求的程式邏輯簡單，那真的也不需要參考設計模式的方式設計，但工程師們就是專門處理複雜問題，化繁為簡的職業。你面對的問題絕不簡單，你必須要學會可以正確切分程式邏輯的設計模式。

今天要介紹的就是 **Strategy Pattern**

## 主題
**Strategy Pattern**

中文常見名稱 **策略模式**

屬於 Behaviral Patterns 一種，目的是為了封裝演算法，達到流程與演算法的解偶，後續流程可以透過引用不同的演算法物件，取得不同的演算法內容進行需求的處理，並產出相同的結果。

引用上述的買菜例子，我們可封裝三種買菜的過程與方式，而最終都會取到買菜的結果。

使用者專注於結果的取得與後續的處理。專注於業務邏輯層。
開發者則可專注於產生結果的過程與方式。專注於應用模組層。

彼此在工作結構上可以切分得更仔細，專注於各自擅長的領域。

**優點:**
- 高度靈活替換實體類別，避免大量使用 If Else
- 水平擴展容易

**缺點:**
- 垂直擴展困難
- 使用者必須熟知所有策略實體類別

![](https://i.imgur.com/fD9fJgp.png)
*[該圖引用來自 Wiki Strategy Pattern - Class Diagram](https://en.wikipedia.org/wiki/Strategy_pattern)*

## 實行方式
```java=
package designPattern.Strategy;


/**
 * @author kaichen
 * Strategy 模式，將不同的處理行為或邏輯進行封裝，並藉由介面提供接口方法。
 * 由外界決定實現的實體
 */
public class Strategy {
	public static void main(String [] args){
		InitAbstractStrategy initStrategy = new InitStrategyImpl();
		initStrategy.doPay();
		
		InitAbstractStrategy initStrategy2 = new InitStrategyImpl2();
		initStrategy2.doPay();
	}
}

interface InitStrategy {
	public void pay();
	public void beforePay();
	public void afterPay();
}

abstract class InitAbstractStrategy implements InitStrategy {
	public void doPay(){
		beforePay();
		pay();
		afterPay();
	}
}

class InitStrategyImpl extends InitAbstractStrategy {

	@Override
	public void pay() {
		System.out.println("This is Impl 1 Pay()");
	}

	@Override
	public void beforePay() {
		System.out.println("This is Impl 1 beforePay()");
	}

	@Override
	public void afterPay() {
		System.out.println("This is Impl 1 afterPay()");
	}
	
}

class InitStrategyImpl2 extends InitAbstractStrategy {

	@Override
	public void pay() {
		System.out.println("This is Impl 2 Pay()");
	}

	@Override
	public void beforePay() {
		System.out.println("This is Impl 2 beforePay()");
	}

	@Override
	public void afterPay() {
		System.out.println("This is Impl 2 afterPay()");
	}
	
}
```

在範例中建立 **InitStrategy** 的介面，並以 **InitAbstractStrategy** 抽象實作介面後，在抽象建立流程方法，以便流程與方法的解耦合。

隨後建立 **InitStrategyImpl** 與 **InitStrategyImpl2** 等兩個實體，並繼承抽象 **InitAbstractStrategy**，實作介面方法。

呼叫時候透過抽象呼叫實體，我們即可直接使用抽象的流程方法，讓介面負責接口、抽象負責流程、實體負責實作。

總結:
- 介面: 提供接口
- 抽象: 制定流程
- 實體: 實作邏輯

以上述這種方式去處理這一次的範例程式結構。

:::danger
用一句話介紹 Strategy Pattern: **將不同面向的處理模組進行抽出，獨立於流程之外，達到兩者職責分明的設計模式**
:::

首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA)

###### tags: `Design Pattern`