以下文字部分均为本人自己的想法与总结所以未必正确;
代码部分摘录自https://github.com/flyingalex/design-patterns-by-php
工厂方法模式:
优点:弥补了简单工厂的确点,即当要修改类的时候工厂类也需要做出相对应的更改。之所以可以解决简单工厂的问题,是因为工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式在添加新产品的时候就不修改工厂类逻辑而是添加新的工厂子类,符合开放封闭原则,克服了简单工厂模式中缺点
操作步骤:
1、创建抽象工厂类,定义具体工厂的公共接口
2、创建抽象产品类 ,定义具体产品的公共接口
3、创建具体产品类(继承抽象产品类) & 定义生产的具体产品
4、创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法
5、外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
个人比喻:
假如有调用者要买猪肉,现在四个工人,分别能加工鸡肉、鸭肉、猪肉、牛肉,使用简单工厂只需要调用者对工厂说“我要猪肉”就行了。但是问题来了,现在调用者说我要买羊肉,此时工厂里没有羊肉工人,这时候就要修改工厂的代码了。
工厂方法模式解决了简单工厂模式的这个问题。现在成立了集团,集团下很多工厂,并规定了工厂都有“生产工人”这个方法(也就是创建生产者对象),有很多符合该条件的工厂,现在调用者买鸡肉找鸡肉厂,买鸭肉找鸭肉厂,买猪肉找猪肉厂等等。那么调用者想吃牛肉的时候,再造一个牛肉厂就行了。工厂方法模式就不用修改工厂原来的代码了。
<?php
/**
* Created by PhpStorm.
* User: mengzhehao
* Date: 2019/7/9
* Time: 17:01
* Note: 工厂方法模式
*/
class Operation
{
protected $a = 0;
protected $b = 0;
public function setA($a)
{
$this->a = $a;
}
public function setB($b)
{
$this->b = $b;
}
public function getResult()
{
$result = 0;
return $result;
}
}
class OperationAdd extends Operation
{
public function getResult()
{
return $this->a + $this->b;
}
}
class OperationMul extends Operation
{
public function getResult()
{
return $this->a * $this->b;
}
}
/**
* Sub
*/
class OperationSub extends Operation
{
public function getResult()
{
return $this->a - $this->b;
}
}
/**
* Div
*/
class OperationDiv extends Operation
{
public function getResult()
{
return $this->a / $this->b;
}
}
/**
* Interface IFactory
* 工厂的接口
*/
interface IFactory
{
public function CreateOperation();
}
class AddFactory implements IFactory
{
public function CreateOperation()
{
return new OperationAdd();
}
}
class SubFactory implements IFactory
{
public function CreateOperation()
{
return new OperationSub();
}
}
class MulFactory implements IFactory
{
public function CreateOperation()
{
return new OperationMul();
}
}
class DivFactory implements IFactory
{
public function CreateOperation()
{
return new OperationDiv();
}
}
//客户端代码
$operationFactory = new SubFactory();
$operation = $operationFactory->CreateOperation();
$operation->setA(20);
$operation->setB(10);
echo $operation->getResult()."\n";