策略模式(Strategy Pattern)定义了一组策略,分别在不同类中封装起来,每种策略都可以根据当前场景相互替换,从而使策略的变化可以独立于操作者。
大家都写过这样的代码
- if (conditionA) {
- 逻辑1
- } else if (conditionB) {
- 逻辑2
- } else if (conditionC) {
- 逻辑3
- } else {
- 逻辑4
- }
这种代码虽然写起来简单,但是很明显违反了面向对象的 2 个基本原则:
单一职责原则(一个类应该只有一个发生变化的原因):因为之后修改任何一个逻辑,当前类都会被修改
开闭原则(对扩展开放,对修改关闭):如果此时需要添加(删除)某个逻辑,那么不可避免的要修改原来的代码
因为违反了以上两个原则,尤其是当 if-else 块中的代码量比较大时,后续代码的扩展和维护就会逐渐变得非常困难且容易出错
if-else 不超过 2 层,块中代码 1~5 行,直接写到块中,否则封装为方法
if-else 超过 2 层,且块中代码超过 3 行,尽量使用策略模式
下面是PHP策略模式的demo,需求是当需要发送各种通知的时候 , 比如发送短信 ,发送邮件 , 发送微信通知 等等 ,可以拆分成一个个策略
- <?php
- //短信类
- class Sms{
- public function send(){
- echo "send sms";
- }
- }
- //邮件类
- class Email{
- public function send(){
- echo "send email";
- }
- }
- //微信类
- class Weixin{
- public function send(){
- echo "send weixin";
- }
- }
- //存储上面策略的工厂
- class Factory{
- public $products=array();
- public function get($type){
- return $this->products[$type];
- }
- public function register($type){
- $class=ucfirst($type);
- $this->products[$type]=new $class;
- }
- }
- //控制器代码
- class Controller{
- public $types=array("sms","email","weixin");
- public $factory=null;
- public function __construct(){
- //先生成出所有策略的对象
- $this->factory=new Factory();
- foreach($this->types as $t){
- $this->factory->register($t);
- }
- }
- public function doAction(){
- //根据传递的type参数 , 选择使用哪一个策略
- $type="sms";
- $notice=$this->factory->get($type);
- $notice->send();
- $type="email";
- $notice=$this->factory->get($type);
- $notice->send();
- }
- }
- $c=new Controller();
- $c->doAction();