标签:工厂模式
工厂模式属于创建型模式,它提供了一种创建对象的方式。工厂模式是先定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类。使用工厂模式的扩展性高,如果想增加一个产品,只要扩展一个工厂类酒可以了,其屏蔽了产品的具体实现,调用者只需关心产品的接口。工厂模式的精髓即是可以根据不同的参数生成不同的类实例。
比如我们定义一个类来实现两个数的加减乘除,代码如下:
<?php
class Calc{
/**
* 计算结果
*
* @param int|float $num1
* @param int|float $num2
* @param string $operator
* @return int|float
*/
public function calculate($num1,$num2,$operator){
try {
$result=0;
switch ($operator){
case ‘+‘:
$result= $num1+$num2;
break;
case ‘-‘:
$result= $num1-$num2;
break;
case ‘*‘:
$result= $num1*$num2;
break;
case ‘/‘:
if ($num2==0) {
throw new Exception("除数不能为0");
}
$result= $num1/$num2;
break;
}
return $result;
}catch (Exception $e){
echo "您输入有误:".$e->getMessage();
}
}
}
$test=new Calc();
// echo $test->calculate(2,3,‘+‘);//打印:5
echo $test->calculate(5,0,‘/‘);//打印:您输入有误:除数不能为0
?>
当我们需要类再实现一个可以“求余”的运算,便可在switch语句块中添加一个分支语句,代码需要做如下改动:
<?php
class Calc{
public function calculate($num1,$num2,$operator){
try {
$result=0;
switch ($operator){
//......省略......
case ‘%‘:
$result= $num1%$num2;
break;
//......省略......
}
}catch (Exception $e){
echo "您输入有误:".$e->getMessage();
}
}
}
?>
用以上方法实现给计算器添加新的功能运算有以下几个缺点:
1. 需要改动原有的代码块,可能会在为了“添加新功能”而改动原有代码的时候,不小心将原有的代码改错了。
2. 如果要添加的功能很多,比如:’乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’,或者添加一些程序员专用的计算功能,比如:And, Or, Not, Xor,这样就需要在switch语句中添加N个分支语句。想象下,一个计算功能的函数如果有二三十个case分支语句,代码将超过一屏,不仅令代码的可读性大大降低,关键是,为了添加小功能,还得让其余不相关都参与解释,这令程序的执行效率大大降低。
为了解决以上问题我们可以采用工厂模式,思路是这样的,我们可以定义“加减乘除”四个类,这四个类中都有 getValue() 方法,然后定义一个可以创建“加减乘除”的类,我们称之为工厂类,该工厂类中有个工厂方法,我们根据可传入到工厂方法的不同参数(可以是”加减乘除“的数学符号),使用这个工厂类的工厂方法创建“加减乘除”类,然后调用其对应的 getValue() 方法获得返回结果。
工厂模式代码如下:
<?php
//定义接口
interface Calc{
public function getValue($num1,$num2);
}
//创建实现接口的实体类
class Add implements Calc{
public function getValue($num1,$num2) {
return $num1 + $num2;
}
}
class Sub implements Calc{
public function getValue($num1,$num2) {
return $num1 - $num2;
}
}
class Mul implements Calc{
public function getValue($num1,$num2) {
return $num1 * $num2;
}
}
class Div implements Calc{
public function getValue($num1,$num2) {
try {
if($num2 == 0) {
throw new Exception(‘除数不能为0‘);
} else {
return $num1/$num2;
}
} catch (Exception $e) {
echo "错误信息:" . $e->getMessage();
}
}
}
//创建一个工厂,生成基于给定信息的实体类的对象
class Factory{
public static function createObj($operate) {
switch ($operate) {
case ‘+‘:
return new Add();
break;
case ‘-‘:
return new Sub();
break;
case ‘*‘:
return new Mul();
break;
case ‘/‘:
return new Div();
break;
}
}
}
$test = Factory::createObj(‘-‘);
echo $test->getValue(1,4);
?>
这样我们就实现了根据用户输入的操作符实例化相应的对象,进而可完成接下来相应的操作。在软件开发中,php可能要链接mysql,也可能链接sqlserver或者其他数据库,这样我们就可以定义一个工厂类,动态产生不同的数据库链接对象。再比如设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。工厂模式的使用场景有很多,需要读者在实际开发中尝试应用。
标签:工厂模式
原文地址:http://chenxiaolong.blog.51cto.com/8786841/1791874