经常听学Java的同学说起设计模式,今天开始接触一些php的设计模式,觉得策略模式挺有意思。其实使用设计模式的目的,大多是为了提高某种类或功能的可扩展性:这里的可扩展性对于Java和C++等强类型语言是非常有用的,使用了合适的设计模式,你可以不修改原类的代码,而新增若干个类来完成扩展。如果你是php程序猿,你可能会说:这没什么啊,我在原类里新增一个方法来完成不就好了?是的,对于php来说,在源码做点改动是完全可以的,改完之后直接运行测试,但是对于强类型语言比如Java来说,必须重新编译之后才能运行查看结果,而如果原来的项目比较大而且已经完成,那么修改源码再重新编译的时间可能会非常长,几十分钟或者几小时都是有可能的。如果我们使用了设计模式,那么只需要新增一个类完成扩展即可,此时只编译新增的类就会省下很多时间。
下面写一个简单的策略模式来说明:比如在html页面里,有计算两个数的和、差、积、商,最后扩展一种取模运算。如图:
此时提交到php脚本里,可以这样处理:
$cal_type = $_POST['op']; //计算类型:加减乘除 $op1 = $_POST['op1'] + 0; //参数1 $op2 = $_POST['op2'] + 0; //参数2 class calculate{ public function cal($op1, $op2){ if($op == 'add'){ return $op1 + $op2; }elseif($op == 'sub'){ return $op1 - $op2; }elseif(...){ ... } } }如果要新增一种计算方式比如取模运算,那么就要在cal()方法里再加elseif判断,你可能会说,用switch啊,用switch也是一样的需要在原类里修改代码。怎样做到不修改原类而新增类来完成新增的取模运算,这就要用到策略模式。
我们可以每一个运算写成一个类,最后再用一类总的类来控制各种运算。代码和注释如下:
HTML代码部分:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>策略模式s</title> </head> <body> <form action="./strategy_mode.php" method="post"> <input type="text" name="op1"/> <select name="op"> <option value="add">+</option> <option value="sub">-</option> <option value="mul">*</option> <option value="div">/</option> <option value="mode">%</option> </select> <input type="text" name="op2"/> <input type="submit" value="计算" /> </form> </body> </html>php代码部分:
interface to_calculate{ public function cal($op1, $op2); } class cal_add implements to_calculate{ public function cal($op1, $op2){ return $op1 + $op2; } } class cal_sub implements to_calculate{ public function cal($op1, $op2){ return $op1 - $op2; } } class cal_mul implements to_calculate{ public function cal($op1, $op2){ return $op1 * $op2; } } class cal_div implements to_calculate{ public function cal($op1, $op2){ return $op1 / $op2; } } class virtual_cal{ public $calobj; public function __construct($type){ //$type:计算类型 $type = 'cal_' . $type; $this->calobj = new $type; //将具体的计算类放进自身类的属性$calobj里 } public function cal($op1, $op2){ return $this->calobj->cal($op1, $op2); //用$calobj来计算结果 } } $cal_type = $_POST['op']; //计算类型:加减乘除 $op1 = $_POST['op1'] + 0; //参数1 $op2 = $_POST['op2'] + 0; //参数2 //如果新增一种计算,只需新增一个类即可(可扩展性) class cal_mode{ public function cal($op1, $op2){ return $op1 % $op2; } } $virtual_cal = new virtual_cal($cal_type); echo $virtual_cal->calobj->cal($op1, $op2);
你可能觉得这和工厂模式比较像,这两种模式,结构相同,但作用不同,工厂模式着重于创建对象的可扩展性,策略模式着重于对象的行为的可扩展性(动态地让对象选择合适的行为)。打个比方:
工厂模式:根据你给出的目的来生产不同用途的斧子,例如要砍人,那么工厂生产砍人斧子,要伐木就生产伐木斧子。
策略模式:用工厂生产的斧子来做对应的事情,例如用砍人的斧子来砍人,用伐木的斧子来伐木。
参考帖子:http://bbs.csdn.net/topics/310103615#quote