PHP设计模式(一) 策略模式
策略模式可以用来创建可插入、可替换、可重用的组件
策略模式的用意是针对一组算法或逻辑,将每一个算法或逻辑封装到具有共同接口的独立的类中,从而使得它们之间可以相互替换。策略模式使得算法或逻辑可以在不影响到客户端的情况下发生变化。说到策略模式就不得不提及OCP(Open Closed Principle) 开闭原则,即对扩展开放,对修改关闭。策略模式的出现很好地诠释了开闭原则,有效地减少了分支语句。
第一版:只有一个 Lesson 类的课程销售系统。
第二版:使用了继承方法让子类做具体的实现。
第三版:使用了组合的策略模式来代替继承(其中使用一个抽象类来规范具体的策略角色)
策略模式的组成
1.抽象策略角色:策略类,通常由一个接口或者抽象类实现。(L.class.php)
2.具体策略角色:包装了相关的算法和行为。(English.class.php)
3.环境角色:持有一个策略类的引用,最终给客户端调用。(Lesson.class.php)
第四版:多继承与策略模式的对比
多继承:
策略模式:
说明:在未来业务扩展增加的时候,由于类似于arts的类型不断地增加,导致代码量重复,继承的方式显得尤为笨重,但是在这一层面我觉得可以通过trait来解决和改善。通过trait来增加多继承从而实现多样性。
相关代码:
Lession.class.php
<?php
//课程类
abstract class Lesson {
//课程购买人数
private $_num;
//策略属性字段,保存具体策略角色对象的引用,例如English对象或者Math对象
private $_strategy;
//构造方法初始化
public function __construct($_num, $_strategy) {
$this->_num = $_num;
$this->_strategy = $_strategy;
}
//拦截器
public function __get($key) {
return $this->$key;
}
//返回具体策略角色课程所需的费用
public function cost() { //$this表示Lesson类,传递给English
return $this->_strategy->cost($this); //$this->_strategy保存了English对象(new English())
}
//返回具体策略角色购买的课程
public function type() {
return $this->_strategy->type($this);
}
}
?>
L.class.php
<?php
abstract class L {
abstract public function cost(Lesson $_lesson);
abstract public function type(Lesson $_lesson);
}
?>
Arts.class.php
<?php
class Arts extends Lesson {
protected $_discount = 0.85; //父类对象访问子类属性
protected $_type = '文科';
}
?>
English.class.php
<?php
class English extends L {
public function cost(Lesson $_lesson) { //父类对象访问子类属性
return $_lesson->_discount * 300 * $_lesson->_num;
}
public function type(Lesson $_lesson) {
return '您购买的是'.$_lesson->_type.'英语课程!';
}
}
?>
run.php
<?php
require 'Lesson.class.php';
require 'Arts.class.php';
require 'L.class.php';
require 'English.class.php';
$_arts = new Arts(5,new English());
echo $_arts->type().$_arts->cost();
策略模式的优缺点
优点:
1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更
灵活(算法独立,可以任意扩展)。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分 GRASP 原则和常用设计原则,高内聚、低偶合。
缺点:
1、因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。