<?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...