首页 > 语言 > PHP > 正文

php面向对象之工厂模式示例

2024-09-04 11:43:48
字体:
来源:转载
供稿:网友

工厂模式是什么?是不是在工厂做事呢?我相信有一些朋友对于php工厂模式还是有一些不理解,下文整理一些关于工厂模式例子.

简单工厂模式:

①抽象基类:类中定义抽象一些方法,用以在子类中实现

②继承自抽象基类的子类:实现基类中的抽象方法

③工厂类:用以实例化对象

php面向对象之工厂模式示例,先看一种代码:

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

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

缺点:无法灵活的扩展和维护

比如:想要增加一个“求余”运算,需要在switch语句块中添加一个分支语句,代码需要再加一个case进行判断,于是产生了以下问题.

①需要改动原有的代码块,可能会在为了“添加新功能”而改动原有代码的时候,不小心将原有的代码改错了.

②如果要添加的功能很多,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’,或者添加一些程序员专用的计算功能,比如:And, Or, Not, Xor,这样就需要在switch语句中添加N个分支语句,想象下,一个计算功能的函数如果有二三十个case分支语句,代码将超过一屏,不仅令代码的可读性大大降低,关键是,为了添加小功能,还得让其余不相关都参与解释,这令程序的执行效率大大降低.

解决途径:采用OOP的继承和多态思想.

  1. <?php 
  2.      /** 
  3.       * 操作类 
  4.       * 因为包含有抽象方法,所以类必须声明为抽象类 
  5.       */ 
  6.      abstract class Operation{ 
  7.          //抽象方法不能包含函数体 
  8.          abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数 
  9.      } 
  10.      /** 
  11.       * 加法类 
  12.       */ 
  13.      class OperationAdd extends Operation { 
  14.          public function getValue($num1,$num2){ 
  15.              return $num1+$num2
  16.          } 
  17.      } 
  18.      /** 
  19.       * 减法类 
  20.       */ 
  21.      class OperationSub extends Operation { 
  22.          public function getValue($num1,$num2){ 
  23.              return $num1-$num2
  24.          } 
  25.      } 
  26.      /** 
  27.       * 乘法类 
  28.       */ 
  29.      class OperationMul extends Operation { 
  30.          public function getValue($num1,$num2){ 
  31.              return $num1*$num2
  32.          } 
  33.      } 
  34.      /** 
  35.       * 除法类 
  36.       */ 
  37.      class OperationDiv extends Operation { 
  38.          public function getValue($num1,$num2){ 
  39.              try { 
  40.                  if ($num2==0){ 
  41.                      throw new Exception("除数不能为0"); 
  42.                  }else { 
  43.                      return $num1/$num2
  44.                  } 
  45.              }catch (Exception $e){ 
  46.                  echo "错误信息:".$e->getMessage(); 
  47.              } 
  48.          } 
  49.      } 
  50.  ?> 
  51.  
  52.  <?php 
  53.      /** 
  54.       * 操作类 
  55.       * 因为包含有抽象方法,所以类必须声明为抽象类 
  56.       */ 
  57.      abstract class Operation{ 
  58.          //抽象方法不能包含函数体 
  59.          abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数 
  60.      } 
  61.      /** 
  62.       * 加法类 
  63.       */ 
  64.      class OperationAdd extends Operation { 
  65.          public function getValue($num1,$num2){ 
  66.              return $num1+$num2
  67.          } 
  68.      } 
  69.      /** 
  70.       * 减法类 
  71.       */ 
  72.      class OperationSub extends Operation { 
  73.          public function getValue($num1,$num2){ 
  74.              return $num1-$num2
  75.          } 
  76.      } 
  77.      /** 
  78.       * 乘法类 
  79.       */ 
  80.      class OperationMul extends Operation { 
  81.          public function getValue($num1,$num2){ 
  82.              return $num1*$num2
  83.          } 
  84.      } 
  85.      /** 
  86.       * 除法类 
  87.       */ 
  88.      class OperationDiv extends Operation { 
  89.          public function getValue($num1,$num2){ 
  90.              try {  //开源软件:Vevb.com 
  91.                  if ($num2==0){ 
  92.                      throw new Exception("除数不能为0"); 
  93.                  }else { 
  94.                      return $num1/$num2
  95.                  } 
  96.              }catch (Exception $e){ 
  97.                  echo "错误信息:".$e->getMessage(); 
  98.              } 
  99.          } 
  100.      } 
  101.  ?> 

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

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

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

现在还有一个问题未解决,就是如何让程序根据用户输入的操作符实例化相应的对象呢?

解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂.

  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. ?> 

我对些的总结就是:根据传递的参数(对象)不同,调用不同的工厂(类),然后用以实现指定的功能,比较大的好处就是简化了以前函数化编程的switch case,if else之类,进行类的分发,不同的东西调用不同的类.

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表