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