策略模式
将一组特定的行为和算法封装成类
举例:
一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有广告位展示不同的广告。
策略模式从侧面 也反应了 Ioc, 依赖倒置, 控制反转。
只要发现自己正不断地在继承树的各个分支中重复同一个算法,(无论是通过子类还是通过重复条件语句),请将这些算法抽象成独立的类型。
好的代码结构 是重构出来的,或者是改出来的,重要的分析类与类关系结构工具就是 画UML。
问题
我们创建了Question类,并为其添加了mark()方法。现在假设用户回答问题,可以使用多种不同的标记方式,应该怎么办呢?
比如支持简单的MarkLogic语言,直接匹配,以及正则表达式这3种标记方式。
你可能首先想到的是使用子类来实现这些差异,如图11-3所示。
如果只考虑这一方面的变化,这样做还能适应我们的需求。但是想象一下,如果我们被要求支持不同类型的问题-基于文本的问题和支持多媒体的问题,如图,在一个继承树中创建多个子类的方案会产生一些问题。
实现:
<?php
abstract class Question{
protected $prompt;
protected $marker;
function __construct($prompt, Marker $marker)
{
$this->marker= $marker;
$this->prompt = $prompt;
}
function mark($response){
return $this->marker->mark($response);
}
}
class TextQuestion extends Question{
//处理文本问题特有的操作
}
class AVQuestion extends Question{
//处理语音问题特有的操作
}
abstract class Marker{
protected $test;
function __construct($test)
{
$this->test = $test;
}
abstract function mark($response);
}
class MarkLogicMarker extends Marker{
private $engine;
function __construct($test)
{
parent::__construct($test);
//$this->engine = new MarkParse($test);
}
function mark($response){
//return $this->engine->evaluate($response);
return true;
}
}
class MatchMarker extends Marker{
function mark($response){
return ($this->test == $response);
}
}
class RegexpMarker extends Marker{
function mark($response)
{
// TODO: Implement mark() method.
return (preg_match($this->test, $response));
}
}
//下面是客户端代码的示例:
$markers = array(
new RegexpMarker("/f.ve/") ,
new MatchMarker("five"),
new MarkLogicMarker('$input equals "five"')
);
foreach($markers as $marker){
print get_class($marker)."\n";
$question = new TextQuestion("how many beans make five", $marker);
foreach(array("five","four") as $response){
print "\tresponse: $response: ";
if($question->mark($response)){
print "well done\n";
}else {
print "never mind\n";
}
}
}