策略模式
在系统中定义算法并以它们自己的类型封装。
只要发现自己正不断地在继承树的各个分支中重复同一个算法(无论是通过子类还是通过重复条件语句),请将这些算法抽象成独立的类型。当类必须支持同一个接口的多种实现时,最好的办法常常是提取出这些实现,并将它们放置在自己的类型中,而不是通过继承原有的类去支持这些实现。如下结构:
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
{
protected $engine;
function __construct($test)
{
parent::__construct($test);
}
function mark($response)
{
return true;
}
}
class MatchMarker extends Marker
{
function mark($response)
{
return ($this->test == $response);
}
}
class RegexpMarker extends Marker
{
function mark($response)
{
return (preg_match($this->test, $_REQUEST));
}
}
目前MarkLogicMarker类还是个伪类。因为它一直返回true,所以无论用户怎么回答都是正确的。
下面是一些客户端代码示例:
$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";
}
}
}