您的位置:首页 > 编程语言 > PHP开发

PHP学习记录----策略模式

2014-04-04 13:13 375 查看
策略模式可以用来创建可插入,可替换,可重用的组件。

先写一个没有用策略模式的例子:

Lesson.class.php:

<?php
//课程类
class Lesson {
//课程购买人数
private $_num;
//课程类型
private $_type;

//英文课的标识
const ENGLISH = 1;
//数学课的标识
const MATH = 2;

//构造方法初始化
public function __construct($_num,$_type){
$this->_num=$_num;
$this->_type=$_type;
}

//返回购买课程所需的费用
public function cost(){
switch($this->_type){
case self::ENGLISH:
return 300*$this->_num;
break;
case self::MATH:
return 180*$this->_num;
break;
}
}
//返回购买课程的名称
public function courseType(){
switch($this->_type){
case self::ENGLISH:
return '您购买的是英文课';
break;
case self::MATH:
return '您购买的是数学课';
break;
}
}
}
?>
Lesson.php:

<?php
require 'Lesson.class.php';
$_lesson = new Lesson(5,Lesson::ENGLISH);
echo $_lesson->courseType().',总共花费了'.$_lesson->cost().'元';
echo '<br>';
$_lesson = new Lesson(5,Lesson::MATH);
echo $_lesson->courseType().',总共花费了'.$_lesson->cost().'元';
?>
考虑第一个问题:是否可重用? 很明显上述代码是不可重用的,都是单独调用。

考虑第二个问题:是否可插入? 如果我们此时再加入一门新的课程,必须往主类中添加额外的代码,违反了高内聚,低耦合的原则,所以上述代码也不可怎么容易插入。

考虑第桑个问题:是否可替换? 如果将ENGLISH改为CHINESE的话,那么Lesson.php中也要修改,有ENGLISH的地方都要进行修改,造成连锁反应,所以替换也不行。

当项目不断扩展时,它的修改和维护会非常艰难。下面我们来再用继承的方式修改一下上述的代码:

Lesson.class.php:

<?php
//抽象课程类
abstract class Lesson {
//课程购买人数
protected $_num;

//构造方法初始化
public function __construct($_num){
$this->_num=$_num;
}

//返回购买课程所需的费用
abstract public function cost();
//返回购买课程的名称
abstract public function courseType();
}
?>


English.class.php:

<?php
class English extends Lesson {
public function cost(){
return 300*$this->_num;
}
public function courseType(){
return '您购买的是英语课程';
}
}
?>


Math.class.php:

<?php
class Math extends Lesson {
public function cost(){
return 180*$this->_num;
}

public function courseType(){
return '您购买的是数学课程';
}
}
?>
lesson.php:

<?php
require 'Lesson.class.php';
require 'English.class.php';
require 'Math.class.php';
$_english = new English(5);
echo $_english->courseType().',总共需要花费'.$_english->cost();
echo '<br>';
$_math = new Math(5);
echo $_math->courseType().',总共需要花费'.$_math->cost();
?>
如果我们此时想要增加一门新的课程,就不需要再在主类中做任何修改了。只需要再增加一个新的类就行。

现在我们再来进一步使用策略模式来代替继承,因为在以后的扩展和维护中,策略模式要优于继承。

策略模式的组成: 1.策略类,通常由一个接口或抽象类来实现 2.具体的策略角色:包装了相关的算法和行为 3.环境角色:持有一个策略类的引用,最终给客户端调用。

Lesson.class.php:

<?php
//课程类
class Lesson {
//课程购买人数
private $_num;

//策略属性,保存具体策略角色对象的引用
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);
}
//返回具体策略角色购买课程的名称
public function courseType(){
return $this->_strategy->courseType();
}
}
?>
English.class.php:

<?php
class English {
public function cost(Lesson $_lesson){
return 300*$_lesson->_num;
}
public function courseType(){
return '您购买的是英语课程';
}
}
?>
Math.class.php:

<?php
class Math {
public function cost(Lesson $_lesson){
return 180*$_lesson->_num;
}

public function courseType(){
return '您购买的是数学课程';
}
}
?>


lesson.php:
<?php
require 'Lesson.class.php';
require 'English.class.php';
require 'Math.class.php';
//通过不同的参数来改变不同的课程的行为,这种方法实现了类切换,类切换就是多态
$_lesson = new Lesson(5,new Math());
echo $_lesson->courseType().',总共花费了'.$_lesson->cost().'元';
echo '<br>';
$_lesson = new Lesson(5,new English());
echo $_lesson->courseType().',总共花费了'.$_lesson->cost().'元';
?>
以上的代码并不是完全形态的策略模式,下面来看进一步改进后的形式:

我们为子类添加一个父类来统一规范子类:

Lesson.class.php:

<?php
//课程类
class Lesson {
//课程购买人数
private $_num;

//策略属性,保存具体策略角色对象的引用
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);
}
//返回具体策略角色购买课程的名称
public function courseType(){
return $this->_strategy->courseType();
}
}
?>
SuperClass.class.php:

<?php
abstract class SuperCourse {
abstract public function cost(Lesson $_lesson);
abstract public function courseType();
}

?>
Math.class.php:

<?php
class Math extends SuperCourse{
public function cost(Lesson $_lesson){
return 180*$_lesson->_num;
}

public function courseType(){
return '您购买的是数学课程';
}
}
?>
English.class.php:

<?php
class English extends SuperCourse{
public function cost(Lesson $_lesson){
return 300*$_lesson->_num;
}
public function courseType(){
return '您购买的是英语课程';
}
}
?>
lesson.php:

<?php
require 'Lesson.class.php';
require 'SuperCourse.class.php';
require 'English.class.php';
require 'Math.class.php';
//通过不同的参数来改变不同的课程的行为,这种方法实现了类切换,类切换就是多态
$_lesson = new Lesson(5,new Math());
echo $_lesson->courseType().',总共花费了'.$_lesson->cost().'元';
echo '<br>';
$_lesson = new Lesson(5,new English());
echo $_lesson->courseType().',总共花费了'.$_lesson->cost().'元';
?>
这就是一个比较正宗的策略模式-。-
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: