PHP設(shè)計(jì)模式之策略模式(Strategy)入門(mén)與應(yīng)用案例詳解
本文實(shí)例講述了PHP設(shè)計(jì)模式之策略模式(Strategy)入門(mén)與應(yīng)用。分享給大家供大家參考,具體如下:
這個(gè)策略模式,意思就是定義一系列算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可相互替換,使用得算法的變化可獨(dú)立于使用它的客戶(hù),簡(jiǎn)單來(lái)講就是,策略模式設(shè)計(jì)幫助構(gòu)建的對(duì)象不必自身包含邏輯,而是能夠根據(jù)需要利用其他對(duì)象中的算法。
來(lái)看下應(yīng)用場(chǎng)景:
1、 多個(gè)類(lèi)只區(qū)別在表現(xiàn)行為不同,可以使用Strategy模式,在運(yùn)行時(shí)動(dòng)態(tài)選擇具體要執(zhí)行的行為。
2、 需要在不同情況下使用不同的策略(算法),或者策略還可能在未來(lái)用其它方式來(lái)實(shí)現(xiàn)。
3、 對(duì)客戶(hù)隱藏具體策略(算法)的實(shí)現(xiàn)細(xì)節(jié),彼此完全獨(dú)立。
4、客戶(hù)端必須知道所有的策略類(lèi),并自行決定使用哪一個(gè)策略類(lèi),策略模式只適用于客戶(hù)端知道所有的算法或行為的情況。
5、 策略模式造成很多的策略類(lèi),每個(gè)具體策略類(lèi)都會(huì)產(chǎn)生一個(gè)新類(lèi)。
有點(diǎn)模糊是吧,咱就來(lái)看一個(gè)完整的應(yīng)用場(chǎng)景:
例如有一個(gè)CD類(lèi),我們類(lèi)存儲(chǔ)了CD的信息。
原先的時(shí)候,我們?cè)贑D類(lèi)中直接調(diào)用getCD方法給出XML的結(jié)果
隨著業(yè)務(wù)擴(kuò)展,需求方提出需要JSON數(shù)據(jù)格式輸出
這個(gè)時(shí)候我們引進(jìn)了策略模式,可以讓使用方根據(jù)需求自由選擇是輸出XML還是JSON
大概了解了之后,咱們來(lái)看一個(gè)代碼實(shí)例,我在網(wǎng)上找的啊,比較簡(jiǎn)單,大家可以根據(jù)自己需要的來(lái)擴(kuò)展一下,如下:
<?php //策略模式 //cd類(lèi) class cd { protected $cdArr; public function __construct($title, $info) { $this->cdArr['title'] = $title; $this->cdArr['info'] = $info; } public function getCd($typeObj) { return $typeObj->get($this->cdArr); } } class json { public function get($return_data) { return json_encode($return_data); } } class xml { public function get($return_data) { $xml = '<?xml version="1.0" encoding="utf-8"?>'; $xml .= '<return>'; $xml .= '<data>' .serialize($return_data). '</data>'; $xml .= '</return>'; return $xml; } } $cd = new cd('cd_1', 'cd_1'); echo $cd->getCd(new json); echo $cd->getCd(new xml);
咱們接下來(lái),再來(lái)了解一下一個(gè)網(wǎng)上比較經(jīng)典的案例,來(lái)看張圖片:
上面圖片的意思可以按著下面這個(gè)方式來(lái)理解:
1.Joe做了一套相當(dāng)成功的模擬鴨子的游戲。設(shè)計(jì)了一個(gè)超類(lèi)Duck,然后讓各種鴨子繼承這個(gè)類(lèi)。
2.后來(lái)客戶(hù)提出要讓鴨子有飛的能力。所以Joe就在超類(lèi)中加了個(gè)fly()方法,這樣下面的子類(lèi)都有飛行的行為。
問(wèn)題來(lái)了:1>原來(lái)Duck的子類(lèi)中竟然有橡皮鴨,橡皮鴨是不會(huì)飛的?!狫oe用重載的方式,把橡皮鴨的fly()方法設(shè)置為空.
2>覆蓋fly(),我們看到了橡皮鴨的fly()里,沒(méi)有任何代碼,如果以后我們?cè)偬砑觿e的不會(huì)飛的鴨子,那我么還要這么處理嗎?——那么代碼重復(fù)了!
3.上面2的方式我們知道是有問(wèn)題的,所以Joe想到把Duck做成接口,這樣每個(gè)子類(lèi)必須實(shí)現(xiàn)Duck里的方法。這樣就保證每個(gè)鴨子都能根據(jù)自己的需要添加行為。
問(wèn)題來(lái)了:產(chǎn)品經(jīng)常處于更新中,規(guī)格也在不斷的變化。導(dǎo)致每當(dāng)有新鴨子的時(shí)候,Joe就要被迫檢查一遍子類(lèi)是否覆蓋了fly()方法?!?dāng)你修改某個(gè)行為的時(shí)候,你必須得往下追蹤并在每一個(gè)定義此行為的類(lèi)中修改它。
4.綜合以上問(wèn)題,Joe想到了把那些變化的部分從不變化的位置中抽出來(lái)。比如,我們對(duì)fly()行為,做了單獨(dú)的接口FlyBehavior。如果鴨子想要飛行功能的時(shí)候,我們就讓鴨子實(shí)現(xiàn)FlyBehavior.
5.深造:我們想讓鴨子有不同的飛行功能,讓它在運(yùn)行時(shí)候做不同的飛行動(dòng)作。讓鴨子類(lèi)實(shí)現(xiàn)接口,只能讓鴨子有一種行為。
好,接下來(lái)看下代碼實(shí)例:
<?php interface FlyBehavior{ public function fly(); } class FlyWithWings implements FlyBehavior{ public function fly(){ echo "Fly With Wings \n"; } } class FlyWithNo implements FlyBehavior{ public function fly(){ echo "Fly With No Wings \n"; } } class Duck{ private $_flyBehavior; public function performFly(){ $this->_flyBehavior->fly(); } public function setFlyBehavior(FlyBehavior $behavior){ $this->_flyBehavior = $behavior; } } class RubberDuck extends Duck{ } // Test Case $duck = new RubberDuck(); /* 想讓鴨子用翅膀飛行 */ $duck->setFlyBehavior(new FlyWithWings()); $duck->performFly(); /* 想讓鴨子不用翅膀飛行 */ $duck->setFlyBehavior(new FlyWithNo()); $duck->performFly();
運(yùn)行結(jié)果:
Fly With Wings
Fly With No Wings
咱們可以來(lái)總結(jié)下在開(kāi)發(fā)過(guò)程中,這些設(shè)計(jì)模式的設(shè)計(jì)原則,如下:
1.找出應(yīng)用中可能需要變化之處,把它們獨(dú)立出來(lái),不要和那些不需要變化的代碼混在一起;
2.針對(duì)接口編程,不針對(duì)實(shí)現(xiàn)編程;
3.多用組合,少用繼承;
好啦,本次記錄就到這里了。
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《PHP數(shù)組(Array)操作技巧大全》、《PHP基本語(yǔ)法入門(mén)教程》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
- PHP pthreads v3下worker和pool的使用方法示例
- PHP-FPM 設(shè)置多pool及配置文件重寫(xiě)操作示例
- PHP設(shè)計(jì)模式之建造者模式(Builder)原理與用法案例詳解
- PHP設(shè)計(jì)模式之適配器模式(Adapter)原理與用法詳解
- PHP設(shè)計(jì)模式之單例模式入門(mén)與應(yīng)用詳解
- PHP設(shè)計(jì)模式之觀(guān)察者模式入門(mén)與應(yīng)用案例詳解
- php設(shè)計(jì)模式之單例模式用法經(jīng)典示例分析
- php設(shè)計(jì)模式之觀(guān)察者模式定義與用法經(jīng)典示例
- 淺談PHP設(shè)計(jì)模式之對(duì)象池模式Pool
相關(guān)文章
php解析url并得到url中的參數(shù)及獲取url參數(shù)的四種方式
本文給大家介紹php解析url并得到url中的參數(shù)及獲取url參數(shù)的四種方式,涉及到將字符串參數(shù)變?yōu)閿?shù)組,將參數(shù)變?yōu)樽址南嚓P(guān)知識(shí),本文代碼簡(jiǎn)單易懂,感興趣的朋友一起看看吧2015-10-10Thinkphp5.1獲取項(xiàng)目根目錄以及子目錄路徑的方法實(shí)例講解
這篇文章主要介紹了Thinkphp5.1獲取項(xiàng)目根目錄以及子目錄路徑的方法實(shí)例講解,希望正在學(xué)習(xí)TP框架的同學(xué)可以跟著小編一起來(lái)學(xué)習(xí)研究下2021-03-03yii使用bootstrap分頁(yè)樣式的實(shí)例
本篇文章主要介紹了yii使用bootstrap分頁(yè)樣式的實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01PHP實(shí)現(xiàn)的簡(jiǎn)單三角形、矩形周長(zhǎng)面積計(jì)算器分享
這篇文章主要介紹了PHP實(shí)現(xiàn)的簡(jiǎn)單三角形、矩形周長(zhǎng)面積計(jì)算器分享,本文的實(shí)現(xiàn)相對(duì)較簡(jiǎn)單,同時(shí)提供了代碼文件下載,需要的朋友可以參考下2014-11-11thinkphp6使用mysql悲觀(guān)鎖解決商品超賣(mài)問(wèn)題的實(shí)現(xiàn)
這篇文章主要介紹了thinkphp6使用mysql悲觀(guān)鎖解決商品超賣(mài)問(wèn)題的實(shí)現(xiàn)2021-11-11php使用Swoole實(shí)現(xiàn)毫秒級(jí)定時(shí)任務(wù)的方法
這篇文章主要介紹了php使用Swoole實(shí)現(xiàn)毫秒級(jí)定時(shí)任務(wù)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09使用gd庫(kù)實(shí)現(xiàn)php服務(wù)端圖片裁剪和生成縮略圖功能分享
一般用戶(hù)上傳頭像時(shí),都會(huì)讓用戶(hù)自行裁剪圖片。那么php怎么實(shí)現(xiàn)這個(gè)功能呢?php中裁剪圖片主要使用gd庫(kù)的imagecopyresampled方法2013-12-12