LieBrother原文 : "行為型模式:策略模式" 十一大行為型模式之五:策略模式。 簡介 姓名 :策略模式 英文名 :Strategy Pattern 價值觀 :集計謀於一身 個人介紹 : Define a family of algorithms,encapsulate each one,a ...
LieBrother原文:
行為型模式:策略模式
十一大行為型模式之五:策略模式。
簡介
姓名 :策略模式
英文名 :Strategy Pattern
價值觀 :集計謀於一身
個人介紹 :
Define a family of algorithms,encapsulate each one,and make them interchangeable.
定義一組演算法,將每個演算法都封裝起來,並且使它們之間可以互換。
(來自《設計模式之禪》)
你要的故事
先看一張拍得不好看的圖片
每天上完班回到家第一件事情是幹啥?有人一進門就躺在沙發上閉目養神、有人一進門躺在沙發上玩手機、有人一進門就陪自己的小寵物玩等等。而我進門第一件事就是洗澡,洗完澡很容易就把一整天的疲憊感給消除掉,然後就可以開始美好的下班時光。現實沒那麼美好,洗完澡後還要洗衣服,大學手洗了 4 年的衣服,一齣來工作,宿舍第一必需品就是洗衣機。細看洗衣機,有很多種洗衣類型,比如:標準、大物、快洗、輕柔。洗衣類型的區別在於洗衣服的過程不一樣,洗衣過程包括有浸泡、洗滌、漂洗、脫水,還有洗衣服的時間也不一樣。細想可以發現這 4 種洗衣類型其實是洗衣服的 4 種不同的策略,也即是 4 種不同的演算法。根據這個思路,我們可以用代碼實現它,定義一個介面 WashingStrategy 定義洗衣服類型,而這些類型都有各自的洗衣過程,比如標準洗衣類型就包括浸泡、洗滌、漂洗、脫水,而快洗則只包括洗滌、漂洗、脫水。而我們洗衣服則需要選擇某個洗衣類型後,洗衣機就開始工作了。過程如下代碼所示。
public class StrategyTest {
public static void main(String[] args) {
WashingStrategy washingStrategy = new StandardWashingStrategy();
WashingMachine washingMachine = new WashingMachine(washingStrategy);
washingMachine.washingClothes();
}
}
/**
* 洗衣類型
*/
interface WashingStrategy {
void washing();
}
/**
* 洗衣機
*/
class WashingMachine {
private WashingStrategy washingStrategy;
public WashingMachine(WashingStrategy washingStrategy) {
this.washingStrategy = washingStrategy;
}
public void washingClothes() {
this.washingStrategy.washing();
}
}
/**
* 標準
*/
class StandardWashingStrategy implements WashingStrategy{
@Override
public void washing() {
System.out.println("標準流程:");
System.out.println("[浸泡] 10 分鐘");
System.out.println("[洗滌] 2 次,每次 15 分鐘");
System.out.println("[漂洗] 1 次,每次 10 分鐘");
System.out.println("[脫水] 5 分鐘");
System.out.println("總共耗時:55 分鐘");
}
}
/**
* 快洗
*/
class QuickWashingStrategy implements WashingStrategy {
@Override
public void washing() {
System.out.println("快洗流程:");
System.out.println("[洗滌] 1 次,每次 10 分鐘");
System.out.println("[漂洗] 1 次,每次 10 分鐘");
System.out.println("[脫水] 5 分鐘");
System.out.println("總共耗時:25 分鐘");
}
}
/**
* 大物
*/
class BigClothesWashingStrategy implements WashingStrategy {
@Override
public void washing() {
System.out.println("大物流程:");
System.out.println("[浸泡] 30 分鐘");
System.out.println("[洗滌] 3 次,每次 15 分鐘");
System.out.println("[漂洗] 2 次,每次 10 分鐘");
System.out.println("[脫水] 5 分鐘");
System.out.println("總共耗時:100 分鐘");
}
}
/**
* 輕柔
*/
class SoftWashingStrategy implements WashingStrategy {
@Override
public void washing() {
System.out.println("輕柔流程:");
System.out.println("[浸泡] 10 分鐘");
System.out.println("[漂洗] 2 次,每次 15 分鐘");
System.out.println("[脫水] 5 分鐘");
System.out.println("總共耗時:45 分鐘");
}
}
標準流程:
[浸泡] 10 分鐘
[洗滌] 2 次,每次 15 分鐘
[漂洗] 1 次,每次 10 分鐘
[脫水] 5 分鐘
總共耗時:55 分鐘
是不是感覺策略模式很簡單呢?上面代碼就是完整的策略模式示例,是不是感覺有些問題,這 4 種洗衣類型對象完全暴露給了用戶,這也是策略模式的缺點。往往策略模式不會單獨使用,會和其他設計模式一起使用,比如和簡單工廠模式一起使用就可以解決這個對外暴露對象的問題,看下麵代碼。
/**
* 洗衣類型選擇
*/
class WashingFactory {
public static WashingStrategy getWashingStrategy(String type) {
if ("Quick".equals(type)) {
return new QuickWashingStrategy();
}
if ("BigClothes".equals(type)) {
return new BigClothesWashingStrategy();
}
if ("Soft".equals(type)) {
return new SoftWashingStrategy();
}
return new StandardWashingStrategy();
}
}
public class StrategyTest {
public static void main(String[] args) {
WashingStrategy washingStrategy2 = WashingFactory.getWashingStrategy("Soft");
WashingMachine washingMachine2 = new WashingMachine(washingStrategy2);
washingMachine2.washingClothes();
}
}
列印結果:
輕柔流程:
[浸泡] 10 分鐘
[漂洗] 2 次,每次 15 分鐘
[脫水] 5 分鐘
總共耗時:45 分鐘
代碼中使用 WashingFactory 來封裝 4 種策略,使得策略沒有對外暴露,我們也瞭解到設計模式之間具有互補的關係,有些時候並不是單獨存在的。
代碼:
Strategy Pattern
總結
策略模式是一個很好的封裝各種複雜處理的設計模式,讓使用者根據自己的選擇來選中策略,而不用修改其他代碼。當策略太多的時候,可能造成使用方變得複雜、難管理多個策略的問題,利用工廠方法模式可以很好的解決這個難題。這其中也是一個見招拆招的問題,設計模式在真正運用中也是這樣子的,遇到問題使用恰當的設計模式去解決問題。
參考資料:《大話設計模式》、《設計模式之禪》
推薦閱讀:
希望文章對您有所幫助,設計模式系列會持續更新,感興趣的同學可以關註公眾號:LieBrother,第一時間獲取文章推送閱讀,也可以一起交流,交個朋友。