《大话设计模式》- 策略模式


《大话设计模式》- 策略模式

商场收银软件的简易实现 ( 需考虑各种打折,返利等情况 )

重点在于各种收费模式的“多变”, 打 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>


分享到:


相關文章: