上篇文章我们讲过简单工厂是违反开放封闭原则的;
而工厂方法模式就可以规避此问题;
它需要定义工厂的接口;
让工厂的子类来确定实例化哪一个具体的产品类;
延迟了类的实例化;
应用场景
要实例化的对象充满不确定性可能会改变的时候;
要创建的对象的数目和类型是未知的;
结构
1个 interface 或者 abstract 产品父类;
多个实现 interface 或者继承 abstract 的具体产品类;
1个 interface 或者 abstract 工厂父类;
多个实现 interface 或者继承 abstract 的具体工厂类;
具体工厂类和具体产品类一一对应;
在具体工厂类中实例化具体的产品类
示例
要是感觉看起来有点懵咱用代码说话;
抽象类和加减乘数这四个产品类是不用变的;
Operation.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
abstract class Operation {
protected $numberA = 0;
protected $numberB = 0;
abstract public function getResult();
public function setNumberA($number) { $this->numberA = $number; }
public function setNumberB($number) { $this->numberB = $number; }
}
|
Add.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class Add extends Operation {
public function getResult() { return $this->numberA + $this->numberB; } }
|
Sub.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class Sub extends Operation {
public function getResult() { return $this->numberA - $this->numberB; } }
|
Mul.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class Mul extends Operation {
public function getResult() { return $this->numberA * $this->numberB; } }
|
Div.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class Div extends Operation {
public function getResult() { if ($this->numberB == 0) { throw new \InvalidArgumentException('除数不能为0'); } return $this->numberA / $this->numberB; } }
|
下面就开始工厂方法的部分了;
没有什么事情是加一层解决不了的;
如果有那就再加一层;
我们给工厂也创建一个抽象类;
Factory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
abstract class Factory {
abstract public function create(); }
|
然后给加减乘数分别创建工厂并分别返回对应的产品;
AddFactory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class AddFactory extends Factory {
public function create() { return new Add(); } }
|
SubFactory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class SubFactory extends Factory {
public function create() { return new Sub(); } }
|
MulFactory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class MulFactory extends Factory {
public function create() { return new Mul(); } }
|
DivFactory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
class DivFactory extends Factory {
public function create() { return new Div(); } }
|
使用的时候 new 各工厂即可;
运行示例;
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <?php
namespace Baijunyao\DesignPatterns\FactoryMethod;
require __DIR__.'/../vendor/autoload.php';
class Client {
public function bad() { $operation = new Add(); $operation->setNumberA(1); $operation->setNumberB(2); $result = $operation->getResult(); echo $result;
echo '<br>';
$operation = new Add(); $operation->setNumberA(3); $operation->setNumberB(4); $result = $operation->getResult(); echo $result; }
public function good() { $factory = new AddFactory(); $operation = $factory->create(); $operation->setNumberA(1); $operation->setNumberB(2); $result = $operation->getResult(); echo $result; } }
$client = new Client(); $client->bad(); echo '<br>'; $client->good();
|
通过代码我们可以看出;
工厂方法不需要再做判断了;
但是增加了工作量;
每增加一个产品都需要增加对应的工厂;
这就形成了一种特殊的代码重复;
不过式设计模式并不是独立使用的;
很多时候都是多个模式互相配合来弱化各自的缺点;
github示例:https://github.com/baijunyao/design-patterns/tree/master/FactoryMethod

本文为白俊遥原创文章,转载无需和我联系,但请注明来自白俊遥博客