對設計模式的總結之簡單工廠與策略模式
前言
面向對象編程追求的本質-提高擴展性、可維護性、靈活性和復用性。合理利用面向對象6個原則,能夠很好的達到要求。如何利用好就是至關重要的了,前人總結了23+個設計模式能夠讓初學者更容易學到其中的精髓,本文就說說我對本人對簡單工廠模式、策略模式的見解。
簡單工廠模式與策略模式
簡單工廠模式
工作中,常常遇到需要做一個功能(鴨子),這個功能中含有可控個數的子操作功能(鴨子叫,鴨子跑,鴨子飛),而且子功能在不同的情況下處理方式又不相同(成年鴨子/小鴨子叫,成年鴨子/小鴨子跑,成年鴨子/小鴨子飛)。我們首先就會想到,用簡單工廠模式哇。創建一個該功能的抽象基類,再創建多個實現不同邏輯的子類繼承它。最後建立一個工廠類,通過工廠類中類型判斷可生成不同的該功能子類實例。客戶端最後調用工廠和抽象基類操作即可。實現類與類松耦合,既簡單又實用。
基本用法
-
/// <summary> /// 工廠類 /// </summary> public class GameOfInteractive { /// <summary> /// 遊戲返回基類 /// </summary> private static GameAbstract gameServiceCall = null; /// <summary> /// 工廠構造類
View Code
總結
優缺點:工廠模式初步滿足了開放-封閉原則;工廠的使用,降低了對象之間的耦合性,做到了責任分離(客戶端不直接創建對象實例,生產實例交給工廠來做)。
工廠與消費者、原料間的聯系都很緊,如果工廠出了問題,與之相關的所有功能都將癱瘓;每次功能擴展,都需要改動工廠類,違反了高內聚責任分配原則。
使用場景:一般只在很簡單的情況下應用。eg:多數據庫選擇,登錄系統與其他系統做簡單信息交互操作等。
策略模式
萬物隨時變,唯一不變的就是變化。實體經濟蕭條,商場生意不如以往,不想被拍死在沙灘上,就必須增加新的刺激消費的活動 。eg:滿100返10,滿500送自行車,會員卡送積分(積分可以換商品),多級會員打折等促銷等方式。這些促銷方式不是一次性就定下來的,是隨著時間的改變產生的,如果在商場計價系統中直接用簡單工廠模式,算法經常更改,工廠也隨之更改,維護和擴展成本都會逐步增加。考慮到計價功能單一,每個子功能都只做計價,結構固定。可以把具體使用那種計價方式的任務交給客戶端來控制,這樣就產生了策略模式。策略模式與簡單工廠模式很像,都有功能基類和各種擴展的子功能類,唯一不同的就是策略模式強調的是算法封裝,不同的算法,用相應的子類進行實現。
基本用法
-
/// <summary> /// 環境角色 /// </summary> public class Context { /// <summary> /// 需要的策略 /// </summary> private AbstractStrategy strategy = null; /// <summary> /// 計算實際得到工資 /// </summary> /// <param name="overtime"></param> /// <returns></returns> public decimal CalculateSalary(int overtime) { return strategy.CalculateSalary(overtime); } } /// <summary> /// 抽象策略角色 /// </summary> public abstract class AbstractStrategy { protected static int baseOvertime = 80;//每個月基礎加班時間 /// <summary> /// 計算實際得到工資 /// </summary> /// <param name="overtime">加班時間</param> /// <returns></returns> public abstract decimal CalculateSalary(int overtime); } /// <summary> /// 工人工資計算 /// </summary> public class WagesForWorkmen:AbstractStrategy { private static decimal baseSalary = 2800;//基礎工資 private static decimal overtimeSalary = 37.5M;//每小時加班費 private static decimal extraSubsidies = 8.6M;//超出基礎加班時間後每小時另加補助費用 /// <summary> /// 計算實際得到工資 /// </summary> /// <param name="overtime">加班時間</param> /// <returns></returns> public override decimal CalculateSalary(int overtime) { decimal actuallySalary = baseSalary; if (overtime> baseOvertime) { actuallySalary += overtimeSalary * baseOvertime + (overtime - baseOvertime) * (overtimeSalary + extraSubsidies); } else { actuallySalary += overtimeSalary * overtime; } return actuallySalary; } } /// <summary> /// 組長工資計算 /// </summary> public class WagesForGroupLeader:AbstractStrategy { private static decimal baseSalary = 2800;//基礎工資 private static decimal postSalary = 800;//崗位工資 private static decimal overtimeSalary = 40M;//每小時加班費 private static decimal extraSubsidies = 5M;//超出基礎加班時間後每小時另加補助費用 /// <summary> /// 計算實際得到工資 /// </summary> /// <param name="overtime">加班時間</param> /// <returns></returns> public override decimal CalculateSalary(int overtime) { decimal actuallySalary = baseSalary+ postSalary; if (overtime > baseOvertime) { actuallySalary += overtimeSalary * baseOvertime + (overtime - baseOvertime) * (overtimeSalary + extraSubsidies); } else { actuallySalary += overtimeSalary * overtime; } return actuallySalary; } } /// <summary> /// 經理工資計算 /// </summary> public class WagesForManager : AbstractStrategy { private static decimal baseSalary = 8000;//基礎工資 private static decimal overtimeSalary =80M;//每小時加班費 private static decimal extraOvertimeSalary = 0M;//超出基礎加班時間後每小時加班費 /// <summary> /// 計算實際得到工資 /// </summary> /// <param name="overtime">加班時間</param> /// <returns></returns> public override decimal CalculateSalary(int overtime) { decimal actuallySalary = baseSalary; if (overtime > baseOvertime) { actuallySalary += overtimeSalary * baseOvertime + (overtime - baseOvertime) * extraOvertimeSalary; } else { actuallySalary += overtimeSalary * overtime; } return actuallySalary; } }
View Code
總結
優缺點:相對於簡單工廠模式,能避免工廠掛掉,其他相應功能都被牽連的問題;能滿足客戶端高頻率更換功能實現算法要求(不用總是去改工廠類,只需要在客戶端更改調用類)。
策略模式適用於客戶端知道所有的算法或行為的情況,增加了具體功能與客戶端的耦合度。
使用場景:商場計價功能、稅收計算功能、保險行業的參保收益計價功能。
簡單工廠與策略結合
使用簡單工廠時,客戶端需要知道工廠類和功能基類;基本的策略模式,將選擇所用具體實現的職責交給客戶端,本身沒有減除客戶端需要選擇判斷的壓力。能否進優化?可以。將兩者結合起來,讓環境角色(StrategyContext)擁有選擇策略和執行策略兩種功能,客戶端只需要傳遞類型參數調用環境角色即可。
基本用法
-
/// <summary> /// 環境角色 /// </summary> public class Context { /// <summary> /// 需要的策略 /// </summary> private AbstractStrategy strategy = null; /// <summary> /// 獲取策略 /// </summary> /// <returns></returns> public Context(int iType) { switch (iType) { case 1: strategy = new WagesForWorkmen(); break; case 2: strategy = new WagesForGroupLeader(); break; case 3: strategy = new WagesForManager(); break; } } /// <summary> /// 計算實際得到工資 /// </summary> /// <param name="overtime"></param> /// <returns></returns> public decimal CalculateSalary(int overtime) { return strategy.CalculateSalary(overtime); } }
View Code
總結
優缺點:相對於簡單工廠模式、單一策略模式,進一步實現了解耦(客戶端只需和環境角色交互)。
雖然進一步解耦,但是任然存在簡單工廠的問題。
對設計模式的總結之簡單工廠與策略模式