登录注册

18250178511

php工厂模式

作者:admin      时间:2016-06-15 13:49:09

转自:http://www.cnblogs.com/hongfei/archive/2012/07/07/2580776.html

简单工厂模式:
①抽象基类:类中定义抽象一些方法,用以在子类中实现
②继承自抽象基类的子类:实现基类中的抽象方法
③工厂类:用以实例化对象

看完文章再回头来看下这张图,效果会比较好

复制代码
 1 采用封装方式  2  3 php  4 class Calc{  5 /**  6  * 计算结果  7  *  8  * @param int|float $num1  9  * @param int|float $num2 10  * @param string $operator 11  * @return int|float 12 */ 13 public function calculate($num1,$num2,$operator){ 14 try { 15 $result=0; 16 switch ($operator){ 17 case '+': 18 $result= $num1+$num2; 19 break; 20 case '-': 21 $result= $num1-$num2; 22 break; 23 case '*': 24 $result= $num1*$num2; 25 break; 26 case '/': 27 if ($num2==0) { 28 throw new Exception("除数不能为0"); 29  } 30 $result= $num1/$num2; 31 break; 32 } 33  return $result; 34 }catch (Exception $e){ 35 echo "您输入有误:".$e->getMessage(); 36  } 37  } 38  } 39 $test=new Calc(); 40 // echo $test->calculate(2,3,'+');//打印:5 41 echo $test->calculate(5,0,'/');//打印:您输入有误:除数不能为0 42 ?>
复制代码

优点:以上代码使用了面向对象的封装特性,只要有了include这个类,其他页面就可以随便使用了

缺点:无法灵活的扩展和维护
比如:想要增加一个“求余”运算,需要在switch语句块中添加一个分支语句,代码需要做如下改动

复制代码
 1 添加分支语句  2  3 php  4 class Calc{  5 public function calculate($num1,$num2,$operator){  6 try {  7 $result=0;  8 switch ($operator){  9 //......省略...... 10 case '%': 11 $result= $num1%$num2; 12 break; 13 //......省略...... 14  } 15 }catch (Exception $e){ 16 echo "您输入有误:".$e->getMessage(); 17  } 18  } 19  } 20 ?>
复制代码

代码分析:用以上方法实现给计算器添加新的功能运算有以下几个缺点

①需要改动原有的代码块,可能会在为了“添加新功能”而改动原有代码的时候,不小心将原有的代码改错了
②如果要添加的功能很多,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’,或者添加一些程序员专用的计算功能,比如:And, Or, Not, Xor,这样就需要在switch语句中添加N个分支语句。想象下,一个计算功能的函数如果有二三十个case分支语句,代码将超过一屏,不仅令代码的可读性大大降低,关键是,为了添加小功能,还得让其余不相关都参与解释,这令程序的执行效率大大降低
解决途径:采用OOP的继承和多态思想

复制代码
 1 简单工厂模式的初步实现  2 php  3 /**  4  * 操作类  5  * 因为包含有抽象方法,所以类必须声明为抽象类  6 */  7 abstract class Operation{  8 //抽象方法不能包含函数体  9 abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数 10  } 11 /** 12  * 加法类 13 */ 14 class OperationAdd extends Operation { 15 public function getValue($num1,$num2){ 16 return $num1+$num2; 17  } 18  } 19 /** 20  * 减法类 21 */ 22 class OperationSub extends Operation { 23 public function getValue($num1,$num2){ 24 return $num1-$num2; 25  } 26  } 27 /** 28  * 乘法类 29 */ 30 class OperationMul extends Operation { 31 public function getValue($num1,$num2){ 32 return $num1*$num2; 33  } 34  } 35 /** 36  * 除法类 37 */ 38 class OperationDiv extends Operation { 39 public function getValue($num1,$num2){ 40 try { 41 if ($num2==0){ 42 throw new Exception("除数不能为0"); 43 }else { 44 return $num1/$num2; 45  } 46 }catch (Exception $e){ 47 echo "错误信息:".$e->getMessage(); 48  } 49  } 50  } 51 ?>
复制代码

这里采用了面向对象的继承特性,首先声明一个虚拟基类,在基类中指定子类务必实现的方法(getValue())

分析:通过采用面向对象的继承特性,我们可以很容易就能对原有程序进行扩展,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’等等。

复制代码
php /**
     * 求余类(remainder)
     * */ class OperationRem extends Operation { public function getValue($num1,$num2){ return $num1%$num12;
        }
    } ?>
复制代码

我们只需要另外写一个类(该类继承虚拟基类),在类中完成相应的功能(比如:求乘方的运算),而且大大的降低了耦合度,方便日后的维护及扩展

现在还有一个问题未解决,就是如何让程序根据用户输入的操作符实例化相应的对象呢?
解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂
代码如下:

复制代码
 1 php  2 /**  3  * 工程类,主要用来创建对象  4  * 功能:根据输入的运算符号,工厂就能实例化出合适的对象  5  *  6 */  7 class Factory{  8 public static function createObj($operate){  9 switch ($operate){ 10 case '+': 11 return new OperationAdd(); 12 break; 13 case '-': 14 return new OperationSub(); 15 break; 16 case '*': 17 return new OperationSub(); 18 break; 19 case '/': 20 return new OperationDiv(); 21 break; 22  } 23  } 24  } 25 $test=Factory::createObj('/'); 26 $result=$test->getValue(23,0); 27 echo $result; 28 ?>

发表评论

评论列表

匿名

You reported it fantastically! <a href="https://rxdiflucan.com/">diflucan</a>

2020-01-04 20:22:32

匿名

With thanks. I enjoy it. <a href="https://rxdiflucan.com/">fluconazole</a>

2020-01-04 11:56:04

匿名

Kudos. Ample facts. <a href="https://rxdiflucan.com/">fluconazole medication</a>

2020-01-04 06:45:19

匿名

You've maegnad a first class post http://gzkish.com [url=http://vwjisgcjc.com]vwjisgcjc[/url] [link=http://leklribc.com]leklribc[/link]

2018-11-03 20:25:07

匿名

You've maegnad a first class post http://gzkish.com [url=http://vwjisgcjc.com]vwjisgcjc[/url] [link=http://leklribc.com]leklribc[/link]

2018-11-03 20:24:25