【读书笔记-重构与模式】 策略模式Strategy--封装变化

Strategy模式:

定义一系列的算法,把他们一个个封装起来,并且是他们可以相互替换,Strategy模式使算法可以独立于使用它的用户而变化。
具体来说,策略模式的关键特征包括:

意图:可以根据上下文,使用不同的业务规则或者算法。

问题:对所需算法的选择取决于发出请求的用户或则要处理的数据。如果只有一些不会变化的算法,就不需要该模式。

解决方案:对算法的选择和算法的实现相分离。允许根据上下文进行选择。

参与者与协作者:。。。。。。。。。

效果:定义了一系列的算法。可以不适用条件语句或者switch语句来调用。各个算法拥有相同的接口。

实现:让使用算法的类包含一个抽象类,该抽象类具有一个抽象方法指定如何调用算法。每个派生类按照需要实现算法。

根据面向对象的一些忠告:“考虑设计中什么是可变的”,“对变化的概念进行封装”,“优先使用对象组合聚集,而不是类继承”。由此我们的作法是:

1.寻找变化,将他封装在一个单独的类中。

2.将这个类包含在另一个类中。

《深入php面向对象模式和实践》中给出的策略模式的例子:

假设我们已经穿捡了一个标记语言,现在测试需要一些问题,因此我们创建了Question类,并为其添加了mark( )方法。假设用户回答问题时可以使用多种不同的标记方式,应该怎么办呢?

比如,现在要支持简单的markLogic语言,直接匹配以及正则表达式匹配三种标记方式。可能首先想到的是使用子类来实现。

如果只是这一个方面的需求,这么做还是能够适应我们的需求的,但是如果我们被要求支持不同的类型==基于文本的问题和基于多媒体的问题,在一个继承树中穿件多个子类的方案会产生一些问题。


因此,“只要发现自己正在不断地在几成熟的各个分支中重复同一个算法(无论是通过子类还是通过重复条件语句)请将这些算法封装成独立的类型。”。

UML图示:


实现:

abstract class Question{
    protected $promp;
    protected $marker;

    public function __construct($promp,Marker $marker){
        $this->marker = $marker;
        $this->promp = $promp;
    }

    abstract  function mark($response);
}

class TextQuestion extends Question{
    public function mark($response){
        echo  "[text-response:]".$response.PHP_EOL;
        return $this->marker->mark($response);
    }
}

class AVQuestion  extends Question{
    public function mark($response){
        echo "[Av-response:]".$response.PHP_EOL;
        return $this->marker->mark($response);
    }
}
class MarkLogicMarker extends Marker{
    private $engine;
    public function __construct( $test ){
        parent::__construct($test);
        $this->engine = new MarkPaser($test);
    }
    public function mark($response){
        return $this->engine->evaluate( $response );
    }
}

class MatchMarker extends Marker{
    public function mark($response){
        return ($this->test == $response);
    }
}

class RegexMarker extends Marker{
    public function mark($response){
        return ( preg_match($this->test,$response) );
    }
}

class Config{
    public static $configs = array(
        'what is baby?'=>'yes',
        'how can i love U?'=>'of course',
        'may be tomorrow?'=>'yeah',
        'should it be like this?'=>'maybe',
        'the result is?'=>'1+1',
    );
}

class MarkParser{
    private $test;
    public function __construct($test){
        $this->test = $test;
    }

    public function evaluate( $response ){
        assert($response);
        assert(in_array($response,array_keys(Config::$configs)));
        return Config::$configs[$response];
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值