设计模式(二十一)策略
一、定義
定義一系列算法類,將每一個算法封裝起來,并讓它們可以相互替換。策略模式讓算法獨立于使用它的客戶而變化。策略模式是一種對象行為型模式,又稱為政策(Policy)模式。
二、描述
包含以下三個角色:1、Context(環境類):環境類是使用算法的角色,它在解決某個問題(即實現某個功能)時可以采用多種策略。在環境類中維持一個對抽象策略類的引用實例,用于定義所采用的策略。
2、Strategy(抽象策略類):抽象策略類為所支持的算法聲明了抽象方法,是所有策略類的父類,它可以是抽象類或具體類,也可以是接口。
3、ConcreteStrategy(具體策略類):具體策略類實現了在抽象策略類中聲明的算法,在運行時,具體策略類對象將覆蓋在環境類中定義的抽象策略類對象,使用一種具體的算法實現某個業務功能。
三、例子
X公司為某電影院開發了一套影院售票系統,在該系統中需要為不同類型的用戶提供不同的電影票打折方式,具體打折方案如下:
(1)學生憑學生證可享受票價8折優惠;
(2)年齡在10周歲以及以下的兒童可以享受每張票減免10元的優惠(原始票價需要大于20元);
(3)影院VIP用戶除享受票價八折優惠外還可以進行積分,積分累計到一定額度可以換取電影院贈送的獎品;
該系統在將來還可能會根據需求引入更多的打折方案
MovieTicket:環境類
public class MovieTicket
{
private double _price;
private IDiscount _discount;
public double Price
{
get
{
return _discount.Calculate(_price);
}
set
{
_price = value;
}
}
public IDiscount Discount
{
set
{
_discount = value;
}
}
}
IDiscount:抽象策略類
public interface IDiscount
{
double Calculate(double price);
}
StudentStrategy、VIPStrategy、ChildrenStrategy:學生折扣、VIP折扣、兒童折扣,充當具體策略
public class StudentDiscount : IDiscount
{
public double Calculate(double price)
{
Console.WriteLine("學生票:");
return price * 0.8;
}
}
public class VIPDiscount : IDiscount
{
public double Calculate(double price)
{
Console.WriteLine("VIP票:");
Console.WriteLine("增加積分!");
return price * 0.5;
}
}
public class ChildrenDiscount : IDiscount
{
public double Calculate(double price)
{
Console.WriteLine("兒童票:");
return price - 10;
}
}
Program:測試代碼
MovieTicket mt = new MovieTicket();
double originalPrice = 60.0;
double currentPrice = originalPrice;
mt.Price = originalPrice;
Console.WriteLine("原始票價:{0}", originalPrice);
Console.WriteLine("----------------------------------------");
IDiscount discount = new VIPDiscount();
if (discount != null)
{
mt.Discount = discount;
currentPrice = mt.Price;
}
Console.WriteLine("折后票價:{0}", currentPrice);
Console.ReadLine();
四、總結
1、優點
(1)提供了對開閉原則的完美支持,用戶可以在不修改原有系統的基礎上選擇具體算法或行為,也可以靈活地增加新的算法或行為。
(2)策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行為族,恰當地使用繼承可以把公共的代碼移到抽象策略類中,從而避免代碼重復。
(3)策略模式提供了一種可以替換繼承關系的辦法。如果不使用策略模式,那么使用算法的環境類就可能會有一些子類,每一個子類提供一種不同的算法。但是,這樣一來算法的使用就和算法本身混在一起,不符合單一職責原則,決定使用哪一種算法的邏輯和該算法本身混合在一起,從而不可能再獨立演化,而且使用繼承無法實現算法或行為在程序運行時的動態切換。
(4)使用策略模式可以避免多重條件選擇語句。多重條件選擇語句不易維護,它把采取哪一種算法或行為的邏輯與算法或行為本身的實現邏輯混合在一起,將它們全部硬編碼在一個龐大的多重條件選擇語句中,比直接繼承環境類的辦法還要原始和落后。
(5)策略模式提供了一種算法的復用機制,由于將算法單獨提取出來封裝在策略類中,因此不同的環境類可以方便地復用這些策略類。
2、缺點
(1)客戶端必須知道所有的策略類,并自行決定使用哪一個策略。這就意味著客戶端必須理解這些算法的區別,以便適時選擇恰當的算法。換而言之,策略模式只適用于客戶端知道所有的算法或行為的情況。
(2)策略模式將造成系統產生很多的具體策略類,任何細小的變化都將導致系統要增加一個具體策略類。
(3)無法同時在客戶端同時使用多個策略類,也就是說,在使用策略模式時,客戶端每次只能使用一個策略類,不支持一個策略類完成部分功能后再使用另一個策略類來完成剩余功能的情況。
總結
以上是生活随笔為你收集整理的设计模式(二十一)策略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 日常Bug排查-集群逐步失去响应
- 下一篇: 如何快速部署本地训练的 Bert-VIT