PHP面向对象之策略模式

  策略模式按我个人的理解说就是将类中重复使用的代码分离出来形成一个策略类,其他类想要调用的话,首先在初始化的时候就要把这个策略类作为参数传递进来即形成一种组合关系,然后在类内部就可以直接调用这个策略类中的逻辑了。

  简单说一下类的组合与聚合关系(很长一段时间里对这种关系一直比较懵,代码看多了,并查看了一些资料才稍微有些概念,这里单独拿出来说一下),类的组合关系类似一个人,人要是死了身体的各个器官就消亡了,这个器官可以理解成上述的策略类。需要调用这个策略类的类假如生命周期结束,那么这个策略类的生命周期也就结束了,无法单独存在使用。而聚合关系类似一台电脑,这台电脑要是坏了,电脑的部分部件还可以拿出来继续使用(这种关系在看到组合模式的时候会有一个比较清楚的概念)。

  现在来看书中(深入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);        //这里它执行了策略类的逻辑
    }
}

//下面这个二个类继承了Question他们分别有自己的业务逻辑,按原文的说法它们将分别处理用户输入的文本信息和多媒体信息

class TextQuestion extends Question{
    //这里原文也没给什么示例代码,只说了自己想象他的业务逻辑。其实也不必太在意,毕竟主要是为了了解模式的概念。
}

class AVQuestion extends Question {
    
}

//以下的类就是策略类,假如上述的TextQuestion和AVQuestion类中有重复的代码就可以把这个代码分离到这个策略类中

//为啥要分离呢,因为假如要扩展BVQuestion,CVQuestion类其中都重复使用了一个方法(有相同或类似的业务逻辑)比如function mark($response)

//那么每次扩展一个类都要使用function mark($response)时候都要复制粘贴,等要修改这个Mark方法的时候你就头疼了

abstract class Marker{
    protected $test;
    
    function __construct ($test){
        $this->test= $test;
    }


    //这里定义了抽象方法mark,继承他的类必须实现,也就是对于不同的用户录入信息需要不同的实现
    abstract function mark($response);  
}

class MarkLogicMarker extends Marker{
    private $engine;
    function mark($response){    //对于marklogic 语言需要进行的处理
        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,$response));  //对于需要使用正则的用户输入进行的处理
    }
}

//客户端代码
$markers = array(
    new RegexpMarker("/f.ve/"),  //这个定义上述的几个策略类,在下面的代码中将分别使用这几个策略类来进行测试
    new MatchMarker("five"),
    new MarkLogicMarker('$input equals "five"')
);
foreach ($markers as $marker){
    print get_class($marker)."<br/>";
    $question = new TextQuestion("how many beans make five",$marker);  
    foreach(array("five","four") as $response){    // 这里的array("five","four")模拟了用户的输入信息
        print " response: $response:";
        if($question->mark($response)){
            print "well done<br/>";
        } else {
            print "never mind<br/>";
        }
    }
}

复制粘贴一下上面的代码运行一下看看结果吧!上面我说的可能都是废话,自己直接运行代码看看可能学习效果好的多。

最后:路漫漫其修远兮 吾将上下而求索!

原文地址:https://www.cnblogs.com/kerryw/p/6866913.html