《大話設計模式》- 策略模式


《大話設計模式》- 策略模式

商場收銀軟件的簡易實現 ( 需考慮各種打折,返利等情況 )

重點在於各種收費模式的“多變”, 打 N 折, 滿多少返利 X, 消費多少送禮品, 滿多少送積分等等, 都是時常在變動的,可能今天打 8.8 折, 明天不打折, 不可能每次要有變動的時候都去修改代碼, 如果要增加一種優惠活動方式呢?改代碼, 一點也不符合靈活性、擴展性

如果用“簡單工廠模式”來實現, "工廠類" 包含了 "滿300減50"、"滿200減20"、"滿100減10" .... 所有的收費方式, 如果需要增加一種方式,則勢必要修改這個"工廠類",收費方式的需求改動性太強, 單純的 "簡單工廠模式" 無法滿足需求, 但是這些需求有個共同點就是“都是收費的一種方式”, 則可以將各個獨立的收費算法, 再統一封裝起來, 讓各種收費算法之間可以相互替換, 隨意選擇任意哪種收費方式, 這就是策略模式

策略模式是一種定義一系列算法的方法, 從概念上看, 所有這些算法都是完成相同的工作, 只是實現不同而已, 它可以以相同的方式調用所有的算法, 減少了各種算法類與使用算法類之間的耦合, 而且每種算法都有各自獨立的類, 這也就方便了單元測試, 所以只要需要在不同時間使用不同規則的業務, 都可以考慮 "策略模式"

但每次增加一種收費方式 ( 也就是增加一種算法 ) 時, 就需要修改 switch 分支去判斷, 有辦法更優嗎 ? 反射 ...


看一個簡單的 PHP 示例:

<code>// 抽象算法類
namespace Mode\\Strategy;
abstract class Strategy {
protected $price = 1200;
abstract public function algorithmInterface();
}/<code>
<code>// 具體算法 A
namespace Mode\\Strategy;
class ConcreteStrategyA extends Strategy {
public function __construct($rebate = 0.8) {
// ...
}

public function algorithmInterface() {
// TODO: Implement algorithmInterface() method.
}
}/<code>
<code>// 具體算法 B
namespace Mode\\Strategy;
class ConcreteStrategyB extends Strategy {
protected $full = 300;
protected $return = 100;
public function __construct($full = 300, $return = 100) {
$this->full = $full;
$this->return = $return;
}
public function algorithmInterface() {
// TODO: Implement algorithmInterface() method.
$num = floor($this->price / $this->full);
return $num * $this->return;
}
}

// ....../<code>
<code>// 上下文
namespace Mode\\Strategy;
class Context {
protected $strategy;
public function __construct(Strategy $strategy) {
$this->strategy = $strategy;
}
public function contextInterface() {
return $this->strategy->algorithmInterface();
}
}/<code>
<code>// 結合 "簡單工廠模式"
namespace Mode\\Strategy;
class ContextFactory {
protected $type;
public function __construct($type = '打5折') {
$this->type = $type;
}
public function getResult() {
$context = null;
switch($this->type){
case '打5折':
$context = new Context(new ConcreteStrategyA(0.5));
break;
case '滿500返100':
$context = new Context(new ConcreteStrategyB(500, 100));
break;
}
return $context->contextInterface();
}
}/<code>
<code>// 調用
require '../autoload.php';
use Mode\\Strategy\\ContextFactory;
$context = new ContextFactory('滿500返100');
echo '
';
echo '消費1200元,商場促銷活動滿500返100, 總的返: ';
echo $context->getResult();
/<code>


分享到:


相關文章: