15
05月
2020
策略模式
模式定义
策略模式(Strategy),又叫算法簇模式,定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化,即封装变化的算法。
策略模式的优势
易于扩展,增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合开放封闭原则
使用策略模式可以避免使用多重条件转移语句(if ... else)
策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换 每个策略类使用一个策略类,符合单一职责原则
客户端与策略算法解耦,两者都依赖于抽象策略接口,符合依赖反转原则
客户端不需要知道都有哪些策略类,符合最小知识原则
策略模式的缺陷
策略模式,当策略算法太多时,会造成很多的策略类
客户端不知道有哪些策略类,不能决定使用哪个策略类,可以考虑使用IOC容器和依赖注入的方式来解决
代码示例
Strategy\ComparatorInterface.class.php
<?php namespace Strategy; interface ComparatorInterface { public function compare($a, $b); }
Strategy\DateComparator.class.php
<?php namespace Strategy; class DateComparator implements ComparatorInterface { public function compare($a, $b) { $aDate = strtotime($a['date']); $bDate = strtotime($b['date']); if($aDate == $bDate) { return 0; } else { return $aDate < $bDate ? -1 : 1; } } }
Strategy\IdComparator.class.php
<?php namespace Strategy; class IdComparator implements ComparatorInterface { public function compare($a, $b) { if($a['id'] == $b['id']) { return 0; } else { return $a['id'] < $b['id'] ? -1 : 1; } } }
Strategy\Context.class.php
<?php namespace Strategy; class Context { private $strategy; public function __construct($strategy) { $this->strategy = $strategy; } public function getCompare($a, $b) { return $this->strategy->compare($a, $b); } }
Strategy\StrategyTest.php
<?php spl_autoload_register(function ($className){ $className = str_replace("\\", "/", $className); include $className . ".class.php"; }); use Strategy\IdComparator; use Strategy\DateComparator; use Strategy\Context; $a = array( 'id' => 1, 'date' => '2020-05-12' ); $b = array( 'id' => 1, 'date' => '2020-05-13' ); $strategy = new Context(new IdComparator()); echo $strategy->getCompare($a, $b); echo "\n"; $strategy = new Context(new DateComparator()); echo $strategy->getCompare($a, $b); echo "\n";
测试示例:
php Strategy/StrategyTest.php 输出: 0 -1
总结
策略模式将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。
代码地址:https://github.com/798256478/design-patterns/tree/master/Strategy