策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
举例:超市促销活动,分别有原价,5折,满300减50,使用策略模式……
通过抽象方法形式
<?php /** * 抽象活动算法类 */ namespace strategy; abstract class StrategyAbstract { /** * 具体活动算法方法 * @return mixed */ public abstract function doAction($money); }
<?php /** * 满减算法产品类 */ namespace strategy; class ManJianStrategy extends StrategyAbstract { public function doAction($money) { echo ‘满减算法:原价‘. $money .‘元‘; } }
<?php /** * 打折算法产品类 */ namespace strategy; class DaZheStrategy extends StrategyAbstract { /** * 具体算法实现 * @param $money * @return mixed|void */ public function doAction($money) { echo ‘打折算法:原价‘. $money .‘元‘; } }
<?php /** * 策略工厂类 */ namespace strategy; class StrategyFind { private $strategy_mode; /** * 初始时,传入具体的策略对象 * @param $mode */ public function __construct($mode) { $this->strategy_mode = $mode; } /** * 执行打折算法 * @param $money */ public function get($money) { $this->strategy_mode->doAction($money); } }
<?php //入口文件 namespace strategy; include ‘../autoload.php‘; // 满减折算 $mode1 = new StrategyFind(new ManJianStrategy()); $mode1->get(100); echo ‘<br>‘; // 满减活动 $mode2= new StrategyFind(new DaZheStrategy()); $mode2->get(100);
策略模式就是使用封装一个公共抽象算法,每个算法(比如,打折算法,满减算法)实现这个接口,然后搞个策略工厂类来调用这些算法。
举例2: 假如有一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有的广告位展示不同的广告。在传统的代码中,都是在系统中加入各种if else的判断,硬编码的方式。如果有一天增加了一种用户,就需要改写代码。使用策略模式,如果新增加一种用户类型,只需要增加一种策略就可以。其他所有的地方只需要使用不同的策略就可以。
首先声明策略的接口文件,约定了策略的包含的行为。然后,定义各个具体的策略实现类。
通过封装接口形式
UserStrategy.php 文件 <?php /* * 声明策略文件的接口,约定策略包含的行为。 */ interface UserStrategy { function showAd(); function showCategory(); }
FemaleUser.php 女性用户女装 <?php class FemaleUser implements UserStrategy { function showAd(){ echo "2016冬季女装"; } function showCategory(){ echo "女装"; } }
MaleUser.php 电子产品类 <?php class MaleUser implements UserStrategy { function showAd(){ echo "IPhone6s"; } function showCategory(){ echo "电子产品"; } }
Page.php//入口文件执行 <?php class Page { protected $strategy; function index(){ echo "AD"; $this->strategy->showAd(); echo "<br>"; echo "Category"; $this->strategy->showCategory(); echo "<br>"; } function setStrategy(UserStrategy $strategy){ $this->strategy=$strategy; } } $page = new Page(); if(isset($_GET[‘male‘])){ $strategy = new MaleUser(); }else { $strategy = new FemaleUser(); } $page->setStrategy($strategy); $page->index();
通过以上方式,可以发现,在不同用户登录时显示不同的内容,但是解决了在显示时的硬编码的问题。如果要增加一种策略,只需要增加一种策略实现类,然后在入口文件中执行判断,传入这个类即可。实现了解耦,实现依赖倒置和控制反转
通过接口的方式,使得类和类之间不直接依赖。在使用该类的时候,才动态的传入该接口的一个实现类。如果要替换某个类,只需要提供一个实现了该接口的实现类,通过修改一行代码即可完成替换。