策略模式定義了一系列的算法屁使,并將每一個算法封裝起來猎莲,而且使它們還可以相互替換流济。策略模式讓算法獨立于使用它的客戶而獨立變化锐锣,即封裝變化的算法。
適用場景:
1绳瘟、 多個類只區(qū)別在表現(xiàn)行為不同雕憔,可以使用Strategy模式,在運行時動態(tài)選擇具體要執(zhí)行的行為糖声。
2斤彼、 需要在不同情況下使用不同的策略(算法),或者策略還可能在未來用其它方式來實現(xiàn)蘸泻。
3琉苇、 對客戶隱藏具體策略(算法)的實現(xiàn)細節(jié),彼此完全獨立悦施。
4并扇、客戶端必須知道所有的策略類,并自行決定使用哪一個策略類抡诞,策略模式只適用于客戶端知道所有的算法或行為的情況穷蛹。
5、 策略模式造成很多的策略類昼汗,每個具體策略類都會產(chǎn)生一個新類肴熏。
有時候可以通過把依賴于環(huán)境的狀態(tài)保存到客戶端里面,可以使用享元模式來減少對象的數(shù)量顷窒。
UML類圖:
角色分析:
抽象策略角色(RotateItem):策略類蛙吏,通常由一個接口或者抽象類實現(xiàn)。
具體策略角色(ItemX):包裝了相關(guān)的算法和行為。
環(huán)境角色(ItemContext):持有一個策略類的引用鸦做,最終給客戶端調(diào)用璧疗。
具體代碼實現(xiàn):
<?php
/**
* Created by PhpStorm.
* User: Jiang
* Date: 2015/5/16
* Time: 21:46
*/
/**抽象策略角色
* Interface RotateItem
*/
interface RotateItem
{
function inertiaRotate();
function unInertisRotate();
}
/**具體策略角色——X產(chǎn)品
* Class XItem
*/
class XItem implements RotateItem
{
function inertiaRotate()
{
echo "我是X產(chǎn)品,我慣性旋轉(zhuǎn)了馁龟。<br/>";
}
function unInertisRotate()
{
echo "我是X產(chǎn)品,我非慣性旋轉(zhuǎn)了漆魔。<br/>";
}
}
/**具體策略角色——Y產(chǎn)品
* Class YItem
*/
class YItem implements RotateItem
{
function inertiaRotate()
{
echo "我是Y產(chǎn)品坷檩,我<span style='color: #ff0000;'>不能</span>慣性旋轉(zhuǎn)。<br/>";
}
function unInertisRotate()
{
echo "我是Y產(chǎn)品改抡,我非慣性旋轉(zhuǎn)了矢炼。<br/>";
}
}
/**具體策略角色——XY產(chǎn)品
* Class XYItem
*/
class XYItem implements RotateItem
{
function inertiaRotate()
{
echo "我是XY產(chǎn)品,我慣性旋轉(zhuǎn)阿纤。<br/>";
}
function unInertisRotate()
{
echo "我是XY產(chǎn)品句灌,我非慣性旋轉(zhuǎn)了。<br/>";
}
}
class contextStrategy
{
private $item;
function getItem($item_name)
{
try
{
$class=new ReflectionClass($item_name);
$this->item=$class->newInstance();
}
catch(ReflectionException $e)
{
$this->item="";
}
}
function inertiaRotate()
{
$this->item->inertiaRotate();
}
function unInertisRotate()
{
$this->item->unInertisRotate();
}
}
測試代碼:
<?php
/**
* Created by PhpStorm.
* User: Jiang
* Date: 2015/5/16
* Time: 21:46
*/
header("Content-Type:text/html;charset=utf-8");
require_once "./Strategy/Strategy.php";
$strategy=new contextStrategy();
echo "<span style='color: #ff0000;'>X產(chǎn)品</span><hr/>";
$strategy->getItem('XItem');
$strategy->inertiaRotate();
$strategy->unInertisRotate();
echo "<span style='color: #ff0000;'>Y產(chǎn)品</span><hr/>";
$strategy->getItem('YItem');
$strategy->inertiaRotate();
$strategy->unInertisRotate();
echo "<span style='color: #ff0000;'>XY產(chǎn)品</span><hr/>";
$strategy->getItem('XYItem');
$strategy->inertiaRotate();
$strategy->unInertisRotate();
優(yōu)點:
1欠拾、 策略模式提供了管理相關(guān)的算法族的辦法胰锌。
策略類的等級結(jié)構(gòu)定義了一個算法或行為族。
恰當(dāng)使用繼承可以把公共的代碼轉(zhuǎn)移到父類里面藐窄,從而避免重復(fù)的代碼资昧。
2、 策略模式提供了可以替換繼承關(guān)系的辦法荆忍。
繼承可以處理多種算法或行為格带。
如果不是用策略模式,那么使用算法或行為的環(huán)境類就可能會有一些子類刹枉,每一個子類提供一個不同的算法或行為叽唱。但是,這樣一來算法或行為的使用者就和算法或行為本身混在一起微宝。決定使用哪一種算法或采取哪一種行為的邏輯就和算法或行為的邏輯混合在一起棺亭,從而不可能再獨立演化。繼承使得動態(tài)改變算法或行為變得不可能芥吟。
3侦铜、 使用策略模式可以避免使用多重條件轉(zhuǎn)移語句。
多重轉(zhuǎn)移語句不易維護钟鸵,它把采取哪一種算法或采取哪一種行為的邏輯與算法或行為的邏輯混合在一起钉稍,統(tǒng)統(tǒng)列在一個多重轉(zhuǎn)移語句里面,比使用繼承的辦法還要原始和落后棺耍。
缺點:
1贡未、客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。
這就意味著客戶端必須理解這些算法的區(qū)別俊卤,以便適時選擇恰當(dāng)?shù)乃惴惸奂贰Q言之,策略模式只適用于客戶端知道所有的算法或行為的情況消恍。
2岂昭、 策略模式造成很多的策略類,每個具體策略類都會產(chǎn)生一個新類狠怨。
有時候可以通過把依賴于環(huán)境的狀態(tài)保存到客戶端里面约啊,而將策略類設(shè)計成可共享的,這樣策略類實例可以被不同客戶端使用佣赖。換言之恰矩,可以使用享元模式來減少對象的數(shù)量。
參考:
大話設(shè)計模式》憎蛤,作者程杰外傅。
https://blog.csdn.net/jhq0113/article/details/45771863