Chap5:行爲型設計模式————策略模式

由於最近在學策略模式,因此想先跳過建立型設計模式中得適配器模式php

定義

策略模式,顧名思義,就是提供多個策略的模式,用戶在不一樣的狀況下能夠選擇不一樣的策略,好比商場的打折策略(不一樣節假日不一樣的折扣方式),旅遊出行的方式(提供飛行,或者火車,或者大巴的方式)。再進一步講,就是把這些同一個系列的不一樣的算法封裝起來,讓它們可以被客戶自由地使用。算法

UML圖

Drawn by StarUML設計模式

clipboard.png

實例

大學課程(Lesson)中,有這樣的兩種課程,一種演講(Lecture),一種研討會(Seminar),兩種都須要進行收費,而且有不一樣的收費機制(chargeType),前者是固定收費(FixedCost),後者則是按小時收費(TimeCost)less

CostStrategy.phpui

<?php
//CostStrategy類,抽象策略類,Context經過調用這個類來調用該類的具體策略A、B類
//其實是經過抽象類或者接口封裝算法的標識,咱們把封裝算法的接口稱做策略
abstract class CostStrategy{
    //定義收費策略的抽象方法,課程與收費機制
    
    abstract function cost(Lesson $lesson);
    abstract function chargeType();
}

?>

TimeCostStrategy.phpthis

<?php
//TimeCostStrategy類,至關於UML圖中的ConcreteStrategyA
class TimeCostStrategy extends CostStrategy{

    //按時長消費,調用上下文中得getDuration()獲取課程時長,並定義每小時消費5
    public function cost(Lesson $lesson){
        return ($lesson->getDuration() * 5);  
    public function chargeType(){
        return 'Hourly rate';
    }

}
?>

FixedCostStrategy.phpurl

<?php
//FixedCostStrategy類,至關於UML圖中得ConcreteStrategyB
class FixedCostStrategy extends CostStrategy{
    public function cost(Lesson $lesson){
        return 30;        //固定收費30
    }
    public function chargeType(){
        return 'Fixed rate';
    }

}
?>

lesson.phpspa

<?php
//Lesson類,至關於UML圖中得Context上下文類
class Lesson{
    public $duration;        //訂價策略爲TimeCostStrategy時的時長
    public $strategy;
    public function __construct($duration,CostStrategy $costStrategy){
        $this->duration = $duration;
        $this->strategy = $costStrategy;
    }
    public function cost(){
        return $this->strategy->cost($this);
    }
    public function chargeType(){
        return $this->strategy->chargeType();
    }
    public function getDuration(){
        return $this->duration;
    }

    //其它方法
}
?>

Lecture.php.net

<?php
//Lecture類,是對上下文(Lesson)的繼承
//UML圖中沒有標註出上下文的子類,所以設計模式要具體狀況具體分析
class Lecture extends Lesson{

}
?>

Seminar.php設計

<?php
//Seminar類,對上下文的繼承
class Seminar extends Lesson{

}
?>

Client.php

<?php
//一次性將全部須要用到的類都引用進來
function __autoload($classname){
    $classpath = "./".$classname.".php";
    if (file_exists($classpath)) {
        require_once($classpath);
    }
}

$Seminar = new Seminar(4,new FixedCostStrategy());
echo 'The cost type is '.$Seminar->chargeType().',and the cost is '.$Seminar->cost();
?>

優勢

  1. 上下文(Context)和具體策略(ConcreteStrategy)是鬆耦合關係。所以上下文只知道它要使用某一個實現Strategy接口類的實例,但不須要知道具體是哪個類

  2. 策略模式知足「開-閉原則」。當增長新的具體策略時,不須要修改上下文類的代碼,上下文就能夠引用新的具體策略的實例

  3. 消除冗餘的if..else...語句

缺點

  1. 客戶端須要知道每個策略類,而且知道這些類有什麼不一樣,所以要在策略行爲與客戶行爲密切相關的時候才使用這種模式,把策略暴露給客戶

  2. 策略模式會產生不少策略,所以開銷問題也是須要考慮的問題

  3. Context與Strategy之間沒必要要的通訊開銷。ConcreteStrategy類共享Strategy,所以須要實現Strategy中的全部抽象方法,若是有的具體策略類比較簡單,但仍是必需要去實現它的抽象方法,所以會增長沒必要要的開銷

參考:
1.設計模式 ( 十八 ) 策略模式Strategy(對象行爲型)
2.深刻PHP:面向對象、模式與實踐(第3版)

相關文章
相關標籤/搜索