php设计模式及应用场景博客_php设计模式(三)简单工厂模式

本来这篇文章早就写完了;

d375fca16ebee5ab0597fcd2e3e56037.png

最先准备用 IOS 和 Android 举例;

但是后来考虑到工厂方法和抽象工厂模式;

又用小米和华为重写了一遍;

这样可以方便的扩充低配版的红米和荣耀;

但还是觉得讲的不清楚;

最后采用了程杰老师《大话设计模式》书中的加减乘除举例;

把 C# 的代码转化并加上自己的理解写成 PHP 代码;

在此感谢程杰老师;

反复写了3种示例终于把这篇文章定稿了;

简单工厂并不属于23种设计模式;

它的实现和它的名字气质很符;

就是简单;

但是它使用的比较多;

当面对产品经理那句让人肝儿颤的"此处不要写死以后可能会改"的时候;

以及"以后可能要增加**功能"的时候;

那我们都可以先构思下是否适合简单工厂模式;

先来说说应用场景;

应用场景

在不确定有多少种操作的时候;

比如说运算符号 + - * / ;

结构

1个工厂;

1个 interface 或者 abstract 产品父类;

多个实现 interface 或者继承 abstract 的具体产品类;

示例

写一个计算器;

我们先用直观的但是并不优雅的方式来实现;

Bad.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

/**

* 不好的示例

*

* Class Bad

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

class Bad

{

/**

* 计算结果

*

* @param int $numberA

* @param string $operate

* @param int $numberB

* @return int|float|int

*/

public function getResult($numberA, $operate, $numberB)

{

switch ($operate) {

case '+':

$result = $numberA + $numberB;

break;

case '-':

$result = $numberA - $numberB;

break;

case '*':

$result = $numberA * $numberB;

break;

case '/':

if ($numberB != 0) {

$result = $numberA / $numberB;

} else {

throw new \InvalidArgumentException('除数不能为0');

}

break;

default:

throw new \InvalidArgumentException('暂不支持的运算');

}

return $result;

}

}

这个类很简单就是传2个值和一个运算符号计算结果;$program = new Bad();

$result = $program->getResult(1, '+', 2);

echo $result;

但是这种方式很不OOP;

把逻辑判断流程和实现代码各种混杂在一起不利于扩展;

就比如说除法的 case 里面的判断;

这时候我们可以把各种运算独立封装;

先建立一个 abstract ;

Operation.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

/**

* 操作类型抽象类

*

* Class Operation

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

abstract class Operation

{

/**

* 运算符号左边的值

*

* @var int

*/

protected $numberA = 0;

/**

* 运算符号右边的值

*

* @var int

*/

protected $numberB = 0;

/**

* 计算结果

*

* @return mixed

*/

abstract public function getResult();

/**

* 给 numberA 赋值

*

* @param $number

*/

public function setNumberA($number)

{

$this->numberA = $number;

}

/**

* 给 numberB 赋值

*

* @param $number

*/

public function setNumberB($number)

{

$this->numberB = $number;

}

}

然后是四则运算;

Add.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

/**

* 加法

*

* Class Add

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

class Add extends Operation

{

/**

* 计算结果

*

* @return int

*/

public function getResult()

{

return $this->numberA + $this->numberB;

}

}

Sub.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

/**

* 减法

*

* Class Sub

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

class Sub extends Operation

{

/**

* 计算结果

*

* @return int|mixed

*/

public function getResult()

{

return $this->numberA - $this->numberB;

}

}

Mul.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

/**

* 乘法

*

* Class Mul

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

class Mul extends Operation

{

/**

* 计算结果

*

* @return float|int

*/

public function getResult()

{

return $this->numberA * $this->numberB;

}

}

Div.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

/**

* 除法

*

* Class Div

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

class Div extends Operation

{

/**

* 计算结果

*

* @return float|int

*/

public function getResult()

{

if ($this->numberB == 0) {

throw new \InvalidArgumentException('除数不能为0');

}

return $this->numberA / $this->numberB;

}

}

这时候我们就可以使用单独的类计算了;// 计算 1+2

$operation = new Add();

$operation->setNumberA(1);

$operation->setNumberB(2);

$result = $operation->getResult();

echo $result;

echo '
';

// 计算 3+4

$operation = new Add();

$operation->setNumberA(3);

$operation->setNumberB(4);

$result = $operation->getResult();

echo $result;

当我们在代码中大量的 new 了加减乘除;

如果说我们需要要把 Add 改成 Addition ;

或者说 new 的时候需要传个参数;

这就坑爹了;

全场改起来想想都心累;

于是被这种场景坑惨了的前辈们就总结出了简单工厂模式;

张大眼睛有请我们的主角 Factory 上场;

Factory.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

/**

* 工厂类

*

* Class Factory

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

class Factory

{

/**

* 创建一种运算

*

* @param $operate

* @return Add|Div|Mul|Sub

*/

public function create($operate)

{

switch ($operate) {

case '+':

$result = new Add();

break;

case '-':

$result = new Sub();

break;

case '*':

$result = new Mul();

break;

case '/':

$result = new Div();

break;

default:

throw new \InvalidArgumentException('暂不支持的运算');

}

return $result;

}

}

当我们把这都拆开了来看的时候;

就会发现简单这个名字真是没白起;

它就是把 Bad.php 中的 case 换成具体的类;$factory = new Factory();

$operation = $factory->create('+');

$operation->setNumberA(1);

$operation->setNumberB(2);

$result = $operation->getResult();

echo $result;

因为我们全场都是 new 的 Factory ;

并没有 new 具体的 Add 类;

当我们面临把 Add 改成 Addition 的时候;

我们只需要在 Factory 中改一处 new Add() 就行了;

运行示例

index.php<?php

namespace Baijunyao\DesignPatterns\SimpleFactory;

require __DIR__.'/../vendor/autoload.php';

/**

* 客户端

*

* Class Client

* @package Baijunyao\DesignPatterns\SimpleFactory

*/

class Client

{

/**

* 不好的示例

*/

public function bad()

{

$program = new Bad();

$result = $program->getResult(1, '+', 2);

echo $result;

}

/**

* 不好的示例2

*

* @return int

*/

public function bad2()

{

// 计算 1+2

$operation = new Add();

$operation->setNumberA(1);

$operation->setNumberB(2);

$result = $operation->getResult();

echo $result;

echo '
';

// 计算 3+4

$operation = new Add();

$operation->setNumberA(3);

$operation->setNumberB(4);

$result = $operation->getResult();

echo $result;

}

/**

* 好的示例

*/

public function good()

{

$factory = new Factory();

$operation = $factory->create('+');

$operation->setNumberA(1);

$operation->setNumberB(2);

$result = $operation->getResult();

echo $result;

}

}

$client = new Client();

$client->bad();

echo '
';

$client->bad2();

echo '
';

$client->good();

看似是很美好了;

然鹅;

如果我们要再增加新的运算;

那就需要改 Factory 增加 case ;

遇到可能性多的场景那 case 想想都可怕;

这就违反了开放封闭原则;

开放封闭原则简单来说就是对扩展开放对修改封闭;

理想情况下我们是不应该再改动 Factory 类的;

增加新运算应该使用扩展的方式;

这就是简单工厂的弊端了;

为此我们就需要了解下篇文章的工厂方法模式了;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值