<?php
/**
* 工厂方法模式演变
*
* 比萨加盟店
* 背景:随着比萨店的发展,有更多人想成为比萨加盟店。
*/
/**
* 每家加盟店都可能想要提供不同风味的比萨(比方说纽约、芝加哥、加州),这受到了开店地点影响。
*/
/**
* 我们已经有一个做法。。。
* 如果利用SimpleFactory,写出三种不同的工厂,分别为NYPizzaFactory、ChicagoPizzaFactory、CaliforniaPizzaFactory,那么各地加盟店都有适合的工厂可以使用,这是一种做法。
*/
$NYPizzaFactory = new NYPizzaFactory();
$nyStore = new PizzaStore($NYPizzaFactory);
$nyStore->orderPizza("veggie");
$ChicagoPizzaFactory = new NYPizzaFactory();
$chicagoStore = new PizzaStore($ChicagoPizzaFactory);
$chicagoStore->orderPizza("veggie");
/**
* 但是你想要多一些质量控制。。。。
* 在推广SimpleFactory时,你发现加盟店的确是采用你的工厂创建比萨,但其他部分,却开始采用他们自创的流程。
* 烘烤的做法有些差异、不要切片、使用其他厂商的盒子。
*/
/**
* 让子类决定,给比萨店使用框架。
* 有个做法可以让比萨制作活动局限于pizzaStore类,而同时又能让这些加盟店依然可以自由制作该区域的风味。
* 所有做的事情,就是把 createPizza() 设置为“抽象方法”,然后为每个区域风味创建一个PizzaStore 的子类。
* 抽象、接口实现多态。
*/
abstract class PizzaStore {
//public $factory;
//public function __construct(SimpleFactory $simpleFactory ) {
// $this->factory = $simpleFactory;
//}
public function orderPizza($type) {
//为了让系统有弹性,我们很希望这是一个抽象类或接口。
//$pizza = $this->factory->createPizza($type); //变化部分
$pizza = $this->createPizza($type);
$pizza->prepare(); //准备
$pizza->bake(); //烘烤
$pizza->cut(); //切片
$pizza->box(); //包装
return $pizza;
}
abstract public function createPizza($type);
}
/**
* 现在已经有了PizzaStore 超类,让 NYPizzaStore,ChicagoPizzaStore等 都继承这个PizzaStore,由子类决定如何制作比萨。
*
*/
/**
* 子类如何做决定
* 关于这个方面,需要从PizzaStore的orderPizza()方法观点来看,更进一步地,orderPizza()方法对pizza做了许多事情(准备、烘烤、切片、包装)
* 但由于Pizza对象是抽象的,orderPizza()并不知道哪些实际的具体类参与了进来,这不是orderPizza()方法决定的,换句话,这就是解耦。
* 那么,子类是实时作出这样的决定吗?不是,但从orderPizza()的角度来看,如果选择在NYStylePizzaStore订购比萨,就是由这个子类(NYStylePizzaStore)决定。
* 严格来说,并非由这个子类实际做“决定”,而是由“顾客”决定到哪一家风味比萨店才决定了比萨风味。
*/
class NYPizzaStore extends PizzaStore {
public function createPizza($type) {
if ("cheese" == $type) {//奶酪比萨
$pizza = new NYStyleCheesePizza();
} elseif ("greek" == $type) {//希腊比萨
$pizza = new NYStyleGreekPizza();
} elseif ("pepperoni" == $type) {//香肠比萨
$pizza = new NYStylePepperoniPizza();
} else {
return null;
}
return $pizza;
}
}
$NYPizzaStore = new NYPizzaStore();
$pizza = $NYPizzaStore->orderPizza('cheese');
/**
* 注意 orderPizza 已经实现了createPizza
*/
/**
* 总结
* 工厂方法模式 定义了一个创建对象的接口,但由子类决定要实例化的类时哪一个。工厂方法让类把实例化推迟到子类。
* 问:简单工厂与工厂方法的差异
* 答:工厂方法是用继承扩展了一个类,而简单工厂,工厂是另一个pizzastore使用对象。
* 子类的确看起来像简单工厂。简单工厂把全部的事情,在一个地方处理完了。然而工厂方法却是创建一个框架,让子类决定要如何实现。
* 比方说,在工厂方法中,orderPizza()方法提供了一般框架,以便创建比萨。orderPizza()依赖工厂方法创建具体类,并制造出实际的比萨。
*/
参考资料 :Head First 设计模式