設計模式 二 策略模式

2022-05-03 04:51:10 字數 4924 閱讀 8492

<?php/**

* 接下來看的是策略模式,舉得例子是商場搞活動

* 商場搞活動中需要不停的變化**方式,有打折啦,滿減啦,積分啦等等,而且打折力度也不一樣,積分也不一樣

* 所以就需要使用策略模式,將變化封裝。策略模式的主要特點就是封裝變化,那為什麼不使用工廠模式呢,

* 每一次有活動我在工廠中新增乙個選項,然後例項化乙個新的類,這樣不也是可以麼。那就下了就對比一下兩個模式的不一樣,

* 看看為什麼使用策略模式 */

//先從最基礎的構建開始,實現乙個最簡單的功能,不需要考慮封裝繼承等

// 服務端

$total = 0;

function shop($price, $commodity

) //

客戶端$total = shop(1.2, 2);

echo

$total;

<?php

//上述實現了正常銷售情況,那接下來經理需要搞活動,要給商品打折,有不同的打折力度

// 服務端

$total = 0;

//0: 五折, 1:8折, 2:9折

function shop($price, $commodity, $type

)

return

$total;}

//客戶端

$total = shop(1.2, 2, 1);

echo

$total;/*

* * 新增加了打折力度後,服務端需要修改的地方就比較多,如果現在經理又需要新增滿減的活動,有的要滿減,有的要在打折的基礎上滿減

* 如果按照當前的架構來實現的話,只能是在switch中不斷的新增新的選項,同時要和客戶端約定好0是什麼,1是什麼等等,如果商場開了5年

* 經理搞活動搞了2,300次,而且每次還搞的不一樣,那這個**將變的很龐大,很不好維護,而且客戶端與服務端對於type的約定也會導致bug的產生

* 因此此處就需要使用物件導向的三大特性,之前還學習了簡單工廠模式,正好用來實現這個功能

* 實現思路:

* 1,將折扣封裝成乙個抽象類,

* 2,然後不同的折扣規則繼承這個抽象類

* 3,新建乙個建立工廠類,然後根據不同的打折規則,例項化不同的折扣規則

*/

<?php

//抽象收費基類

abstract

class

cashsuper

//正常收費類

class cashnormal extends

cashsuper}//

打折收費類

class cashrebate extends

cashsuper

public

function acceptcash($money

) }//

滿減活動類

class cashreturn extends

cashsuper

public

function acceptcash($money

)

return

$result

; }}//

建立工廠內,實現自動例項化物件

class

cashfactory

return

$this->cs;

}}//

客戶端$csf = new

cashfactory();

$cs = $csf->cteatecashaccept('正常收費');

$res = $cs->acceptcash(100);

echo

$res

;$cs = $csf->cteatecashaccept('打折');

$res = $cs->acceptcash(100);

echo

$res

;$cs = $csf->cteatecashaccept('滿300減100');

$res = $cs->acceptcash(600);

echo

$res;/*

* * 上述方法是使用簡單工廠實現的,但是還是具有缺點的,比較之前實現計算器的時候,

* 計算器的規則是固定的,不會頻繁的改動,但是在此處這些**演算法是不斷更新的

*/

<?php/**

* 針對上述問題,現在就可以引出策略模式

* 先看到策略模式的概念:

* 策略模式定義了演算法家族,分別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變化,不會影響到使用演算法的使用者

* 接下來使用策略模式實現此功能,然後參照**理解上邊的概念 */

//抽象收費基類

abstract

class

cashsuper

//正常收費類

class cashnormal extends

cashsuper}//

打折收費類

class cashrebate extends

cashsuper

public

function acceptcash($money

) }//

滿減活動類

class cashreturn extends

cashsuper

public

function acceptcash($money

)

return

$result

; }}//

原先封裝好的具體活動規則視為3個策略

// 接下來使用策略模式的 context 上下文處理類,就像簡單工廠模式具有建立工廠類一樣

class

cashcontext

public

function getresult($money

) }//

客戶端實現

function shop($type, $money

)

$res = $cs->getresult($money

);

return

$res;}

$res = shop('滿300減100', 600);

echo

$res;/*

* * 此處使用了策略模式,使用了上下文處理類,呼叫者需要使用哪種策略將對應的策略傳給進來就好

* 到此處就有些懵逼,這策略模式和簡單工廠模式到底有什麼區別啊,而且還把判斷邏輯移動到客戶端去處理

* 難道每個使用此類的方法都自己去判斷啊?

* * 如果這樣思考那就片面了,並不是要去對比兩個模式哪個好哪個壞,而且每當碰到這種需求的時候,要學會使用哪種模式去解決當前遇到的問題

* 此處使用策略模式,可以很好的將具體演算法和客戶端進行了隔離,在未使用策略模式的時候,需要客戶端自己去呼叫演算法的實現方法,

* 這樣做的好處是什麼呢,就是降低耦合性,像在此處客戶端只接觸到了cashcontext類,以及他認為的演算法實現方法getresult;

* 這都是屬於cashcontext類的,但是在工廠模式中就需要使用到具體演算法的實現方法acceptcash。

* 我們使用策略模式很好的進行了封裝隔離,只將上下文處理類中的乙個方法暴露給客戶端,大大降低了耦合性,客戶端公升級,服務端公升級改動等都可以

* 很輕鬆的進行。那此處應當理解的就是封裝變化,封裝變化可以降低耦合性。 */

//但是此處將判斷邏輯放到客戶端是不好的,那解決方案就是結合簡單工廠模式,將策略模式有簡單工廠模式結合使用

<?php

//抽象收費基類

abstract

class

cashsuper

//正常收費類

class cashnormal extends

cashsuper}//

打折收費類

class cashrebate extends

cashsuper

public

function acceptcash($money

) }//

滿減活動類

class cashreturn extends

cashsuper

public

function acceptcash($money

)

return

$result

; }}//

原先封裝好的具體活動規則視為3個策略

// 接下來使用策略模式的 context 上下文處理類,就像簡單工廠模式具有建立工廠類一樣

class

cashcontext

$this->cs = $cs

; }

public

function getresult($money

) }//

客戶端實現

function shop($type, $money

) $res = shop('滿300減100', 600);

echo

$res;/*

* * 此處將策略模式與簡單工廠模式的結合使用分別於策略模式,簡單工廠模式進行比對

* * 與簡單工廠模式比對:其實就是增加了乙個地方 getresult這個方法,而這個方法就是策略模式的使用,就是使用這個方法,將客戶端與實際的

* 演算法類進行了隔離,封裝了變化(演算法),降低了耦合性。我客戶端只讓定你這個cashcontext類中的這個方法啊就可以了,和你沒有其他任何的關聯

* 對於不同的演算法來說,我編寫我的演算法就好了,只要我測試我的演算法接受正常的引數時可以正常執行,那就可以了

* * 與策略模式比對:將判斷例項化哪個類放到工廠模式的方法中進行,客戶端需要做的只是傳遞引數即可,工廠方法會根據具體的引數判斷出該例項化哪個類

* 這樣也大大降低了服務端與客戶端的耦合性

*/

設計模式 二 策略模式

定義演算法家族,分別封裝起來,讓它們之間可以互相替換,讓演算法變化,不會影響到使用者 good 適合類中的成員以方法為主,演算法經常變動 簡化了單元測試 因為每個演算法都有自己的類,可以通過自己的介面單獨測試。策略模式和簡單工廠基本相同,但簡單工廠模式只能解決物件建立問題,對於經常變動的演算法應使用...

設計模式(二) 策略模式

策略模式 strategy 它定義了乙個演算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化,不會影響到使用演算法的客戶。現金收費抽象類 abstract class cashsuper 正常收費子類 class cashnormal cashsuper 打折收費子類 class ...

設計模式(二) 策略模式

策略模式定義了演算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化,不會影響到使用演算法的客戶。我們來實現乙個簡單的商場收銀軟體功能來闡述策略模式 1.我們先來定義乙個收費方式的基類,如下 using system namespace strategy 2.收費方案,如下 usin...