PHP简单工厂模式

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

简单工厂模式:

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

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



[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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语句块中添加一个分支语句,代码需要做如下改动

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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的继承和多态思想

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.     /** 
  3.      * 求余类(remainder) 
  4.      * 
  5.      */  
  6.     class OperationRem extends Operation {  
  7.         public function getValue($num1,$num2){  
  8.             return $num1%$num12;  
  9.         }  
  10.     }  
  11. ?>  

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

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

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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. ?>  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值