演算法的封裝與切換 策略模式(一)

2021-09-19 10:29:23 字數 3969 閱讀 2161

俗話說:條條大路通羅馬。在很多情況下,實現某個目標的途徑不止一條,例如我們在外出旅遊時可以選擇多種不同的出行方式,如騎自行車、坐汽車、坐火車或者坐飛機,可根據實際情況(目的地、旅遊預算、旅遊時間等)來選擇一種最適合的出行方式。在制訂旅行計畫時,如果目的地較遠、時間不多,但不差錢,可以選擇坐飛機去旅遊;如果目的地雖遠、但假期長、且需控制旅遊成本時可以選擇坐火車或汽車;如果從健康和環保的角度考慮,而且有足夠的毅力,自行車遊或者徒步旅遊也是個不錯的選擇,

在軟體開發中,我們也常常會遇到類似的情況,實現某乙個功能有多條途徑,每一條途徑對應一種演算法,此時我們可以使用一種設計模式來實現靈活地選擇解決途徑,也能夠方便地增加新的解決途徑。本章我們將介紹一種為了適應演算法靈活性而產生的設計模式——策略模式

sunny軟體公司為某電影院開發了一套影院售票系統,在該系統中需要為不同型別的使用者提供不同的電影票打折方式,具體打折方案如下:

(1) 學生憑學生證可享受票價8折優惠;

(2) 年齡在10周歲及以下的兒童可享受每張票減免10元的優惠(原始票價需大於等於20元);

(3) 影院vip使用者除享受票價半價優惠外還可進行積分,積分累計到一定額度可換取電影院贈送的獎品。

該系統在將來可能還要根據需要引入新的打折方式。

為了實現上述電影票打折功能,sunny軟體公司開發人員設計了乙個電影票類movieticket,其核心**片段如下所示:

//電影票類

class

movieticket

public

void

settype

(string type)

public

double

getprice

()          //計算打折之後的票價

public

double

calculate

()                  //兒童票折後票價計算

else

if(this.type.equalsignorecase("children") && this.price >= 20 )                   //vip票折後票價計算

else

if(this.type.equalsignorecase("vip"))   else  }}

編寫如下客戶端測試**:

class

client

}

編譯並執行程式,輸出結果如下所示:

原始價為:60.0

學生票:

折後價為:48.0

兒童票:

折後價為:50.0

通過movieticket類實現了電影票的折後價計算,該方案解決了電影票打折問題,每一種打折方式都可以稱為一種打折演算法,更換打折方式只需修改客戶端**中的引數,無須修改已有源**,但該方案並不是乙個完美的解決方案,它至少存在如下三個問題:

(1) movieticket類的calculate()方法非常龐大,它包含各種打折演算法的實現**,在****現了較長的if…else…語句,不利於測試和維護

(2) 增加新的打折演算法或者對原有打折演算法進行修改時必須修改movieticket類的源**,違反了「開閉原則」,系統的靈活性和可擴充套件性較差。

(3) 演算法的復用性差,如果在另乙個系統(如商場銷售管理系統)中需要重用某些打折演算法,只能通過對源**進行複製貼上來重用,無法單獨重用其中的某個或某些演算法(重用較為麻煩)。

如何解決這三個問題?導致產生這些問題的主要原因在於movieticket類職責過重,它將各種打折演算法都定義在乙個類中,這既不便於演算法的重用,也不便於演算法的擴充套件。因此我們需要對movieticket類進行重構,將原本龐大的movieticket類的職責進行分解,將演算法的定義和使用分離,這就是策略模式所要解決的問題,下面將進入策略模式的學習。

俗話說:條條大路通羅馬。在很多情況下,實現某個目標的途徑不止一條,例如我們在外出旅遊時可以選擇多種不同的出行方式,如騎自行車、坐汽車、坐火車或者坐飛機,可根據實際情況(目的地、旅遊預算、旅遊時間等)來選擇一種最適合的出行方式。在制訂旅行計畫時,如果目的地較遠、時間不多,但不差錢,可以選擇坐飛機去旅遊;如果目的地雖遠、但假期長、且需控制旅遊成本時可以選擇坐火車或汽車;如果從健康和環保的角度考慮,而且有足夠的毅力,自行車遊或者徒步旅遊也是個不錯的選擇,

在軟體開發中,我們也常常會遇到類似的情況,實現某乙個功能有多條途徑,每一條途徑對應一種演算法,此時我們可以使用一種設計模式來實現靈活地選擇解決途徑,也能夠方便地增加新的解決途徑。本章我們將介紹一種為了適應演算法靈活性而產生的設計模式——策略模式

sunny軟體公司為某電影院開發了一套影院售票系統,在該系統中需要為不同型別的使用者提供不同的電影票打折方式,具體打折方案如下:

(1) 學生憑學生證可享受票價8折優惠;

(2) 年齡在10周歲及以下的兒童可享受每張票減免10元的優惠(原始票價需大於等於20元);

(3) 影院vip使用者除享受票價半價優惠外還可進行積分,積分累計到一定額度可換取電影院贈送的獎品。

該系統在將來可能還要根據需要引入新的打折方式。

為了實現上述電影票打折功能,sunny軟體公司開發人員設計了乙個電影票類movieticket,其核心**片段如下所示:

//電影票類

class

movieticket

public

void

settype

(string type)

public

double

getprice

()          //計算打折之後的票價

public

double

calculate

()                  //兒童票折後票價計算

else

if(this.type.equalsignorecase("children") && this.price >= 20 )                   //vip票折後票價計算

else

if(this.type.equalsignorecase("vip"))   else  }}

編寫如下客戶端測試**:

class

client

}

編譯並執行程式,輸出結果如下所示:

原始價為:60.0

學生票:

折後價為:48.0

兒童票:

折後價為:50.0

通過movieticket類實現了電影票的折後價計算,該方案解決了電影票打折問題,每一種打折方式都可以稱為一種打折演算法,更換打折方式只需修改客戶端**中的引數,無須修改已有源**,但該方案並不是乙個完美的解決方案,它至少存在如下三個問題:

(1) movieticket類的calculate()方法非常龐大,它包含各種打折演算法的實現**,在****現了較長的if…else…語句,不利於測試和維護

(2) 增加新的打折演算法或者對原有打折演算法進行修改時必須修改movieticket類的源**,違反了「開閉原則」,系統的靈活性和可擴充套件性較差。

(3) 演算法的復用性差,如果在另乙個系統(如商場銷售管理系統)中需要重用某些打折演算法,只能通過對源**進行複製貼上來重用,無法單獨重用其中的某個或某些演算法(重用較為麻煩)。

如何解決這三個問題?導致產生這些問題的主要原因在於movieticket類職責過重,它將各種打折演算法都定義在乙個類中,這既不便於演算法的重用,也不便於演算法的擴充套件。因此我們需要對movieticket類進行重構,將原本龐大的movieticket類的職責進行分解,將演算法的定義和使用分離,這就是策略模式所要解決的問題,下面將進入策略模式的學習。

演算法的封裝與切換 策略模式(一)

俗話說 條條大路通羅馬。在很多情況下,實現某個目標的途徑不止一條,例如我們在外出旅遊時可以選擇多種不同的出行方式,如騎自行車 坐汽車 坐火車或者坐飛機,可根據實際情況 目的地 旅遊預算 旅遊時間等 來選擇一種最適合的出行方式。在制訂旅行計畫時,如果目的地較遠 時間不多,但不差錢,可以選擇坐飛機去旅遊...

策略模式 封裝演算法,相互替換

what 官方定義 定義演算法家族,分別封裝起來,讓他們之間可以相互替換,此模式讓演算法的變化不會影響到十四用演算法的客戶 自己總結 封裝策略,讓策略根據要求相互替換 when 需要不同時間應用不同的業務規則,就可以考蘇使用策略模式應對變化 和狀態模式蠻像的 why和狀態模式一樣,這個模式限消除了條...

封裝需求的變更 策略模式和工廠模式(一)

既然避免不了,我們就應該把需要變動的隔離出來,不變的放另外的地方。載入蘋果地圖很方便,官方都有文件,主要是mapkit 框架,這個就不多說了,好,我們把 整合到工程裡面去 cgrect rect uiscreen mainscreen bounds mapview mkmapview alloc i...