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. return $result;
  31. }
  32. }catch (Exception $e){
  33. echo "您输入有误:".$e->getMessage();
  34. }//开源代码phpfensi.com
  35. }
  36. }
  37. $test=new Calc();
  38. // echo $test->calculate(2,3,'+');//打印:5
  39. echo $test->calculate(5,0,'/');//打印:您输入有误:除数不能为0
  40. ?>

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

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

比如:想要增加一个“求余”运算,需要在switch语句块中添加一个分支语句,代码需要做如下改动,添加分支语句,代码如下:

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

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

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

②如果要添加的功能很多,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’,或者添加一些程序员专用的计算功能,比如: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. ?>

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

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

求余类,代码如下:

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

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

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

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

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