title: 「理解策略模式」
url: 「
tags:
策略模式屬於行為型模式。定義了一系列的演算法,並將每乙個演算法單獨封裝起來,使每個演算法之間可以相互替換,並且演算法本身和使用演算法的客戶端是分割開來的。
著重的不是如何實現演算法,而是系統如何根據客戶端的情況來選擇呼叫哪種演算法,從而使程式結構更加靈活,擴充套件性更強。
優點通過抽象、封裝來定義一系列的演算法,使得這些演算法之間可以相互代替,所以為這些演算法定義乙個抽象類或者介面,來約束演算法功能的實現。如果這些演算法有公共的功能,還可以在抽象類中實現這些公共的功能。
實現的這一系列演算法之間是可以相互替換的,是平等的,寫在一起就是if … else …**塊,如果演算法裡面又有條件語句,就構成了多重語句,造成**複雜,閱讀困難。則可以使用策略模式,將演算法分離出來。
擴充套件性高。在策略模式中,當有新的演算法的時候,不需要在if … else …**塊中新增,而是新增乙個新的策略實現類,然後告訴客戶端該策略的宣告,就可以了。 缺點
客戶端必須知道所有策略模式定義出來的演算法,並且知道每個策略實現的功能。
增加了物件的數量。每新增乙個演算法,就單獨封裝出乙個新的策略實現類,如果策略多的話,那麼物件也就多了。
只適合扁平的演算法結構。由於每個策略之間的關係是平等的,可以互相替換的,所以需要呼叫幾個演算法的集合時,就比較困難。
問題重現
現在有乙個影象識別的演算法,影象識別的演算法又細分為身份證識別,營業執照識別。
按照平時的習慣,客戶端傳遞type過來說明要呼叫哪種演算法,服務端根據type來判斷使用哪種演算法。
一般**實現:
public string identifyrecognitionimage(string data)
//將轉換成base64,影象識別需要
string base64 = aliimageutils.getimagestrfrompath(obj.getstring("image_path"));
if (stringutil.isempty(base64))
string type = obj.getstring("type");
obj.put("base64", base64);
jsonobject rejson;
if ("business".equals(type)) else if ("card".equals(type)) else
return new result("識別成功", "data", rejson).tostring();
}
注:data是乙個json格式的字串,其中包含了type-演算法型別,image_path-路徑。
**中使用了if … else …**模組,這樣看起來似乎是沒有什麼大問題,但是擴充套件性差。例如當我們需要新增乙個新的演算法-駕照識別的時候,就需要修改if … else …,每次這樣做比較麻煩。
如果使用策略模式呢?
服務端接收type
public string identifyrecognitionimage(string data)
//將轉換成base64,影象識別需要
string base64 = aliimageutils.getimagestrfrompath(obj.getstring("image_path"));
if (stringutil.isempty(base64))
string type = obj.getstring("type");
obj.put("base64", base64);
//根據type型別獲取相應的實現類
iimagerecognition imagerecognition = aliimageutils.get(type);
jsonobject rejson = imagerecognition.recognize(obj.tojsonstring());
return new result("識別成功", "data", rejson).tostring();
}
定義演算法的介面
/**
* @author sk
* @time 2019/5/15
* @desc 影象識別,後續新增影象識別的時候,只需在請求的data中指定型別type,實現iimagerecognition介面並在type()方法中宣告type即可
* 參考策略模式
**/public inte***ce iimagerecognition
按需實現介面
營業執照識別
/**
* @author sk
* @time 2019/5/15
* @desc 營業執照影象識別
**/@service
public class businessimagerecognition implements iimagerecognition
@override
public string type()
}
身份證識別/**
* @author sk
* @time 2019/5/15
* @desc 身份證影象識別
**/@service
public class cardimagerecognition implements iimagerecognition
@override
public string type()
}
工具類:該類主要是將演算法實現注入到bean中,然後根據type獲取相應的實現類,方便呼叫
/**
* @author sk
* @time 2019/5/15
* @desc 影象識別工具類
**/@component
//用來儲存具體演算法的實現bean
private static final mapmap = new hashmap<>();
@override
throws bean***ception
}public static iimagerecognition get(string type)
return imagerecognition;}}
雖然是暫時加多了**量,但是後續每當新增乙個新的識別演算法時,只需要將該新演算法實現iimagerecognition介面,並宣告type,最後將type告知客戶端即可。
uml類圖
uml時序圖
策略模式體現了開閉原則:策略模式把一系列的可變演算法進行封裝,從而定義了良好的程式結構,在出現新的演算法的時候,可以很容易的將新的演算法實現加入到已有的系統中,而已有的實現不需要修改。
策略模式體現了黎克特制替換原則:策略模式是乙個扁平的結構,各個策略實現都是兄弟關係,實現了同乙個介面或者繼承了同乙個抽象類。這樣只要使用策略的客戶端保持面向抽象程式設計,就可以動態的切換不同的策略實現以進行替換。
參考:
理解js設計模式之策略模式
策略模式的定義 定義一系列的演算法,然後根據實際情況去呼叫 乙個小插曲 最近在專案的過程中接手了乙個比較複雜的需求,由於是舊的專案用新的框架重構,所以能夠看見以前的 吸取下前人 的精華,復用一些可用的 免得自己寫半天。當然這篇的主題是策略模式,不會離題,因為當我完成了version 1 後,專案裡面...
理解js設計模式之策略模式
策略模式的定義 定義一系列的演算法,然後根據實際情況去呼叫 乙個小插曲 最近在專案的過程中接手了乙個比較複雜的需求,由於是舊的專案用新的框架重構,所以能夠看見以前的 吸取下前人 的精華,復用一些可用的 免得自己寫半天。當然這篇的主題是策略模式,不會離題,因為當我完成了version 1 後,專案裡面...
策略模式的理解與應用
策略模式 strategy pattern 也叫作 政策模式 policy 是指定義了演算法組並分別封裝起來,讓他們可以互相替換使得演算法的更改並不會影響使用了演算法的使用者。策略模式屬於行為性設計模式,在策略模式中,乙個類的行為及演算法可以在執行時更改。策略模式重在抽象行為,即將行為抽象為具體的類...