1、引言git
在講策略模式以前,咱們來看零售行業軟件的一個針對客戶類型打折的功能。github
vip客戶打八折,svip客戶打七折。算法
代碼實現:ide
if (customer == "vip") { amount = amount * 0.8; } else if (customer == "svip") { amount = amount * 0.7; }
看代碼,挺簡單的,可是若是今天vip打八折,明天要打7折,那還得改變原有的代碼,這樣就違背了開閉原則。這裏變化的是折扣的計算方式(策略),策略模式就能夠解決這類問題。this
2、概念spa
策略模式是一種對象行爲型模式。策略模式(Strategy Pattern):定義一系列算法,將每個算法封裝起來,並讓它們能夠相互替換。code
3、實現對象
策略模式包含三種角色:Context: 上下文類、Strategy: 抽象策略類、ConcreteStrategy: 具體策略類blog
抽象策略類:ip
public abstract class AbstractDiscountStrategy { public abstract decimal Discount(decimal amount); }
具體策略類:
public class VipDiscountStrategy:AbstractDiscountStrategy { public override decimal Discount(decimal amount) { return amount * 0.8M; } }
public class SVipDiscountStrategy:AbstractDiscountStrategy { public override decimal Discount(decimal amount) { return amount * 0.7M; } }
環境類:
public class StrategyContext { private AbstractDiscountStrategy discountStrategy; public StrategyContext(AbstractDiscountStrategy concreteDiscountStrategy) { this.discountStrategy = concreteDiscountStrategy; } public decimal ExecuteStrategy(decimal amount) { return this.discountStrategy.Discount(amount); } }
調用:
if (customer == "vip") { context = new StrategyContext(new VipDiscountStrategy()); amount = context.ExecuteStrategy(amount); } else if (customer == "svip") { context = new StrategyContext(new SVipDiscountStrategy()); amount = context.ExecuteStrategy(amount); }
能夠看到,應用策略模式後,若是要修改vip客戶的折扣計算方式,只須要修改對應的策略便可,不須要修改客戶端的調用代碼,也不會影響到svip的折扣計算方式,符合開閉原則。
再來一個ssvip客戶,只須要增長一個對應的策略實現類,而且修改客戶端的調用方法便可。
vip和svip的策略能夠互換。
4、總結
從上面的例子能夠看出來,策略模式的優勢是提供了對「開閉原則」的完美支持,用戶能夠在不修改原有系統的基礎上選擇算法或行爲,也能夠靈活地增長新的算法或行爲。
缺點也很明顯,客戶端必須清楚知道每個策略的用途,而且自行決定使用哪個策略,增長了客戶端的負擔,這個問題能夠使用配置的方式來解決。每個策略都須要一個類,會使策略類增多。