策略模式定义了算法族,分别封装起来,让他们之间能够相互替换。该模式让算法独立于使用它的客户而独立变化。php
抽象策略角色: 策略类,一般由一个接口或者抽象类实现。html
具体策略角色:包装了相关的算法和行为。算法
环境角色:持有一个策略类的引用,最终给客户端调用。segmentfault
多个类只区别在表现行为不一样,可使用策略模式,在运行时动态选择具体要执行的行为。工具
须要在不一样状况下使用不一样的策略(算法),或者策略还可能在将来用其它方式来实现。this
对客户隐藏具体策略(算法)的实现细节,彼此彻底独立。设计
定义抽象角色类(定义好各个实现的共同抽象方法)code
定义具体策略类(具体实现父类的共同方法)htm
定义环境角色类(接收保存实例,统一执行策略类接口方法)对象
<?php header('Content-Type:text/html;charset=utf-8'); /** * 策略模式演示代码 * * 为了更好地突出“策略”,咱们这里以出行为例演示,平常出行大概分为如下几种工具:自驾车,公交车,地铁,火车,飞机,轮船 * * 下面一块儿看代码,领会何为策略模式 */ /** * Interface Travel 抽象策略角色 * 约定具体方法 */ interface Travel { public function go(); } /** * Class selfDriving 具体策略角色 * 自驾车 */ class bySelfDriving implements Travel { public function go() { echo '我本身开着车出去玩<br>'; } } /** * Class byBus具体策略角色 * 乘公交 */ class byBus implements Travel { public function go() { echo '我乘公交出去玩<br>'; } } /** * Class byMetro 具体策略角色 * 乘地铁 */ class byMetro implements Travel { public function go() { echo '我乘地铁出去玩<br>'; } } /** * Class byTrain 具体策略角色 * 乘火车 */ class byTrain implements Travel { public function go() { echo '我乘火车出去玩<br>'; } } /** * Class byAirplane 具体策略角色 * 乘飞机 */ class byAirplane implements Travel { public function go() { echo '我乘飞机出去玩<br>'; } } /** * Class bySteamship 具体策略角色 * 乘轮船 */ class bySteamship implements Travel { public function go() { echo '我乘轮船出去玩<br>'; } } /** * Class Mine 环境角色 */ class Mine{ private $_strategy; private $_isChange = false; /** * 构造方法 * 此处使用到了依赖注入和类型约束的概念,详情请参考 * 1.聊一聊PHP的依赖注入(DI) 和 控制反转(IoC) * @link https://segmentfault.com/a/1190000007209266 * 2.浅谈PHP的类型约束 * @link https://segmentfault.com/a/1190000007226476 * * @param Travel $travel */ public function __construct(Travel $travel) { $this->_strategy = $travel; } /** * 改变出行方式 * * @param Travel $travel */ public function change(Travel $travel) { $this->_strategy = $travel; $this->_isChange = true; } public function goTravel() { if ($this->_isChange) { echo '如今改变主意,'; $this->_strategy->go(); } else { $this->_strategy->go(); } } } /** * 客户端使用 */ $strategy = new Mine(new byBus()); // 乘公交 $strategy->goTravel(); // 乘地铁 $strategy->change(new byMetro()); $strategy->goTravel(); // 自驾车 $strategy->change(new bySelfDriving()); $strategy->goTravel(); // 其余根据具体应用选择实现
我乘公交出去玩 如今改变主意,我乘地铁出去玩 如今改变主意,我本身开着车出去玩
策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承能够把公共的代码转移到父类里面,从而避免重复的代码。
策略模式提供了能够替换继承关系的办法。继承能够处理多种算法或行为。若是不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每个子类提供一个不一样的算法或行为。可是,这样一来算法或行为的使用者就和算法或行为自己混在一块儿。决定使用哪种算法或采起哪种行为的逻辑就和算法或行为的逻辑混合在一块儿,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
使用策略模式能够避免使用多重条件转移语句。多重转移语句不易维护,它把采起哪种算法或采起哪种行为的逻辑与算法或行为的逻辑混合在一块儿,通通列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
客户端必须知道全部的策略类,并自行决定使用哪个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道全部的算法或行为的状况。
策略模式形成不少的策略类,每一个具体策略类都会产生一个新类。有时候能够经过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例能够被不一样客户端使用。换言之,可使用享元模式来减小对象的数量。
聊一聊PHP的依赖注入(DI) 和 控制反转(IoC):https://segmentfault.com/a/11...
浅谈PHP的类型约束:https://segmentfault.com/a/11...