工厂模式–简单工厂
简单工厂其实并不是一个设计模式,反而比较像一种编程习惯。我个人的这样总结简单工厂:
创建一个类,封装创建对象的代码。
代码故事:
现在我要开一家披萨店,叫BBK(必败客)披萨,卖很多种披萨:芝士披萨、榴莲披萨等等,我有一个orderPizza(string $type)方法,根据客户传来的type来提供不同的披萨:
if (0 == strcmp('cheese', $type)) {
$this->pizza = new CheesePizza($type);
} elseif (0 == strcmp('veggie', $type)) {
$this->pizza = new VeggiePizza($type);
}
当有更多的披萨出现在菜单上是,就要更多 if和new操作,这明显违背我们之前提到过的原则:
对修改关闭,对拓展开放。
最好的办法就是把这块代码分离出来。是的,这里运用简单工厂的方式:创建一个类,封装创建对象的代码。
这里的芝士披萨、榴莲披萨,他们都是披萨,先创建一个Pizza类:
<?php
namespace SimpleFactory;
class Pizza
{
private $pizza_name;
public function __construct($pizza_name)
{
$this->pizza_name = $pizza_name;
}
public function getPizzaName()
{
return $this->pizza_name;
}
public function prepare(){
return '准备披萨'.$this->pizza_name;
}
public function cut(){
return '切片'.$this->pizza_name;
}
public function box(){
return '包装'.$this->pizza_name;
}
}
然后,提供2中具体的Pizza,CheesePizza:
<?php
namespace SimpleFactory;
class CheesePizza extends Pizza
{
}
和 VeggiePizza ,他们都继承Pizza。
<?php
namespace SimpleFactory;
class VeggiePizza extends Pizza
{
}
然后,创建简单工厂,来生产Pizza,以后当有新的Pizza进来时,只需要修改工厂里的方法就可以了。
<?php
namespace SimpleFactory;
/**
* 简单工厂类
*
* 更像是一种编程习惯而不是设计模式
* Class SimpleFactory
* @package SimpleFactory
*/
class SimpleFactory
{
private $pizza = null;
/**
* 得到Pizza,要知道,可能有多处地方调用这块的代码
*
* @param $type
* @return Pizza
*/
public function createPizza($type)
{
if (0 == strcmp('cheese', $type)) {
$this->pizza = new CheesePizza($type);
} elseif (0 == strcmp('veggie', $type)) {
$this->pizza = new VeggiePizza($type);
}
return $this->pizza;
}
}
最后,店铺(必败客)来提供Pizza,来看:
<?php
namespace SimpleFactory;
/**
* 具体调用工厂的地方,这里是必败客披萨店
*
* Class BBKPizza
* @package SimpleFactory
*/
class BBKPizza
{
private $factory = null;
public function __construct(SimpleFactory $pizza)
{
$this->factory = $pizza;
}
public function orderPizza($type) : Pizza
{
// 制作披萨
$the_pizza = $this->factory->createPizza($type);
// 切片打包
$the_pizza->prepare();
$the_pizza->cut();
$the_pizza->box();
return $the_pizza;
}
}
好了,披萨、工厂、店铺都已经有了,来看下如何点披萨:
<?php
include "Pizza.php";
include "BBKPizza.php";
include "CheesePizza.php";
include "SimpleFactory.php";
include "VeggiePizza.php";
use SimpleFactory\BBKPizza;
use SimpleFactory\SimpleFactory;
$pizza_factory = new SimpleFactory();
$bbk_pizza = new BBKPizza($pizza_factory); // 必败客是调用披萨的地方
$the_pizza = $bbk_pizza->orderPizza('cheese'); // 制作披萨,细节过程在工厂中完成
var_dump($the_pizza->getPizzaName());
不难理解,对吧。
“对修改关闭,对拓展开放”,很多OO原则都应尽量遵守,但你的代码未必都处处严格遵守这些原则。比如当有新的Pizza进来时,你依然要修改工厂的代码,但要注意到,工厂可能会有多个依赖者,而这些依赖者们不用关心工厂中的变化。