🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## **策略模式的定义** 策略(Strategy)模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。 **优点** 1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。 2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。 3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。 4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。 5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。 **缺点** 1. 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。 2. 策略模式造成很多的策略类。 >策略模式是准备一组算法,并将这组算法封装到一系列的策略类里面,作为一个抽象策略类的子类。策略模式的重心不是如何实现算法,而是如何组织这些算法,从而让程序结构更加灵活,具有更好的维护性和扩展性,现在我们来分析其基本结构和实现方法。 ## **策略模式的应用场景** 策略模式在很多地方用到,如[Java](http://c.biancheng.net/java/)SE 中的容器布局管理就是一个典型的实例,Java SE 中的每个容器都存在多种布局供用户选择。在程序设计中,通常在以下几种情况中使用策略模式较多。 1. 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。 2. 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。 3. 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。 4. 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的[数据结构](http://c.biancheng.net/data_structure/)。 5. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,可以使用策略模式,在运行时动态选择具体要执行的行为。 应用场景总结:用于对象间的替换 >[danger]**注意事项:** 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。 ## **模式的结构** 1. 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。 2. 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。 3. 环境(Context)类:持有一个策略类的引用,最终给客户端调用。 ![](https://img.kancloud.cn/0a/e3/0ae344539f86258b9c91a07a8b69568b_716x325.png) ``` //抽象策略类 interface Strategy { public function strategyMethod(); //策略方法 } //具体策略类A class ConcreteStrategyA implements Strategy { public function strategyMethod() { print_r("具体策略A的策略方法被访问!"); } } //具体策略类B class ConcreteStrategyB implements Strategy { public function strategyMethod() { print_r("具体策略B的策略方法被访问!"); } } //环境类 class Context { private $strategy; //Strategy /** * 获取策略类 * @return Strategy [description] */ public function getStrategy() { return $this->strategy; } public function setStrategy(Strategy $strategy) { $this->strategy = $strategy; } public function strategyMethod() { $this->strategy->strategyMethod(); } } class StrategyPattern { public static function main() { $context = new Context(); $strategy = new ConcreteStrategyA(); $context->setStrategy($strategy); $context->strategyMethod(); print_r("<br>-----------------<br>"); $strategy = new ConcreteStrategyB(); $context->setStrategy($strategy); $context->strategyMethod(); } } 结果: 具体策略A的策略方法被访问! ----------------- 具体策略B的策略方法被访问! ``` 例子: ![](https://img.kancloud.cn/65/c8/65c85176e948fa134ad8bddf2fcf9402_703x287.png) ``` interface TripMode { public function getOut(); } class ByTrain implements TripMode { public function getOut() { echo "乘坐火车出行"; } } class ByCar implements TripMode { public function getOut() { echo "坐汽车出行"; } } class SelfDrive implements TripMode { public function getOut() { echo "自驾车出行"; } } class WyTour { private $tm; public function setTripMode(TripMode $tm) { $this->tm = $tm; } public function getTripMode() { return $this->tm; } public function getOut() { $this->tm->getOut(); } } $byCar = new ByCar(); $byTrain = new ByTrain(); $selfDrive = new SelfDrive(); $wt = new WyTour(); $wt->setTripMode($byCar); $wt->getOut(); $wt->setTripMode($byTrain); $wt->getOut(); $wt->setTripMode($selfDrive); $wt->getOut(); ``` 例子: ~~~ /** * 策略模式 Strategy * */ function output($string) { echo $string . "n"; } //策略基类接口 interface IStrategy { public function OnTheWay(); } class WalkStrategy implements IStrategy { public function OnTheWay() { output( '在路上步行'); } } class RideBickStrategy implements IStrategy { public function OnTheWay() { output( '在路上骑自行车'); } } class CarStrategy implements IStrategy { public function OnTheWay() { output( '在路上开车'); } } //选择策略类Context class Context { public function find($strategy) { $strategy->OnTheWay(); } } class Client { public static function test(){ $travel = new Context(); $travel->find(new WalkStrategy()); $travel->find(new RideBickStrategy()); $travel->find(new CarStrategy()); } } Client::test(); ~~~ ## 策略模式的扩展 在一个使用策略模式的系统中,当存在的策略很多时,客户端管理所有策略算法将变得很复杂,如果在环境类中使用策略工厂模式来管理这些策略类将大大减少客户端的工作复杂度,其结构图如图 ![](https://img.kancloud.cn/a7/c3/a7c3f67460c5448c5be1e74b022ab167_800x304.png) ``` //抽象策略类 interface Strategy { public function strategyMethod(); //策略方法 } //具体策略类A class ConcreteStrategyA implements Strategy { public function strategyMethod() { print_r("具体策略A的策略方法被访问!"); } } //具体策略类B class ConcreteStrategyB implements Strategy { public function strategyMethod() { print_r("具体策略B的策略方法被访问!"); } } class StrategyFactory{ static $strategys=array(); public static function put(string $key, Strategy $sy){ StrategyFactory::$strategys[$key]=$sy; } public static function get(string $key){ return StrategyFactory::$strategys[$key]; } public static function strategyMethod($key){ StrategyFactory::$strategys[$key]->strategyMethod(); } } StrategyFactory::put("a", new ConcreteStrategyA()); StrategyFactory::put("b", new ConcreteStrategyB()); StrategyFactory::strategyMethod("a"); ```