自由擴充及切換演算法(功能)
官方說明
定義演算法家族且個別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變動獨立於使用操作物件之外
PS. [家族]表示各演算法(功能)作用相似
主要療效
以IStragegy介面作為Context掛載各ConcreteStragegy的邊界,Context可以隨意切換任何ConcreteStragegy來執行任務;另外,可以當有新的ConcreteStrategy被擴充時,也可輕易的被Context掛載使用。
適用情況
1. 會不斷擴充的演算法(功能)家族
2. 用戶會切換使用不同演算法(功能)
PS. [家族]表示各演算法(功能)作用相同
關鍵心法
1. 將演算法家族必備部分抽出為介面
2. 實作介面之個別演算法
3. 將演算法實體注入用戶中進行操作
應用聯想
開發一隻檔案壓縮程式,預計區分為三種產品線,依序為免費版、去廣告板及企業版,分別使用公司開發的三種壓縮演算方法(普通壓縮、中級壓縮、高級壓縮)。
首先來檢查是否合乎適用情境:
1. 會不斷擴充的演算法(功能)家族
壓縮演算法(ICompressAlgorithm)會不斷的研發精進
PS. 此處[家族]表示各演算法(功能)作用相同,演算法的功能都是作為檔案壓縮使用
2. 用戶會切換使用不同演算法(功能)
銷售產品(Zipper)會依照行銷策略or新演算法問世而調整演算法的使用
實際演練
筆者將搭配關鍵心法來套用策略模式,讓各演算法(ICompressAlgorithm)與產品(Zipper)的耦合性降低,可以輕易地擴充新演算法,且讓產品也可隨意使用。
1. 將演算法家族必備部分抽出為介面
由於各演算法的作用為檔案壓縮,所以抽出壓縮(Compress)作業為介面
interface ICompressAlgorithm
{
// 檔案壓縮
void Compress();
}
2. 實作介面之個別演算法
建立個別檔案壓縮演算法(實作ICompressAlgorithm介面)
class NormalCompressAlgorithm : ICompressAlgorithm
{
public void Compress()
{
Console.WriteLine("普通壓縮");
}
}
class MidLevelCompressAlgorithm : ICompressAlgorithm
{
public void Compress()
{
Console.WriteLine("中級壓縮");
}
}
class HighLevelCompressAlgorithm : ICompressAlgorithm
{
public void Compress()
{
Console.WriteLine("高級壓縮");
}
}
3. 將演算法實體注入用戶中進行操作
* 使用時可以自行組裝產品與其使用之壓縮演算法。
* 切斷了產品與演算法之間的耦合
* 產品只知道需要壓縮,而實際壓縮的方式是透過外部注入的物件來執行。
class Zipper
{
// Fields
private ICompressAlgorithm _compressAlgorithm;
// Constructors
public Zipper(ICompressAlgorithm compressAlgorithm)
{
_compressAlgorithm = compressAlgorithm;
}
// Methods
public void Compress()
{
if (_compressAlgorithm != null)
_compressAlgorithm.Compress();
}
}
static void Main(string[] args)
{
// 檔案壓縮產品(三種)
Zipper normalZipper;
Zipper noAdZipper;
Zipper enterpriseZipper;
// 免費版: 注入普通壓縮演算法
Console.WriteLine("Normal Zipper:");
normalZipper = new Zipper(new NormalCompressAlgorithm());
normalZipper.Compress();
// 去廣告板: 注入中效壓縮演算法
Console.WriteLine("No Ad Zipper:");
noAdZipper = new Zipper(new MidLevelCompressAlgorithm());
noAdZipper.Compress();
// 企業版: 注入高效壓縮演算法
Console.WriteLine("Enterprise Zipper:");
enterpriseZipper = new Zipper(new HighLevelCompressAlgorithm());
enterpriseZipper.Compress();
Console.ReadKey();
}
總結
透過以上實例可發現,套用策略模式可使產品(Zipper)與演算法(ICompressAlgorithm)各司其職,當需產生一新式演算法時,僅需新建類別且實作檔案壓縮演算法介面即可(擴充性高),並不影響任何產品的運作(耦合性低),且針對產品在使用新式演算法上,也只需注入該演算法實體即可,不用對產品類別進行修改(封閉原則);若以此角度設計,將來在系統維護上必定可減經開發者不少的負擔,且功德無量好事一件啊!! XD
若想比較使用前後效益,請參考以下重構系列文章:
[Refactoring] 使用策略模式(Strategy Pattern)進行重構
參考資料
http://teddy-chen-tw.blogspot.tw/2013/08/strategy-pattern.html
http://www.dotblogs.com.tw/joysdw12/archive/2013/03/07/95769.aspx
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !