继续上篇 设计模式学习笔记(开篇)-抽象工厂 工厂模式 简单工厂(2)。
我们上篇说到了工厂模式,同时留下一个问题。当要制造一个工具时,需要选择制造工艺(大小,外形等),指定材料(不锈钢,铝合金等),颜色(红,黑,绿)等。
从上篇学习的工厂模式中,我们很容易想到。为了扩展性,我们会为工艺选择提供一个工厂方法,材料选择提供一个工厂,染料(颜色)选择提供一个工厂方法。这样我们通过三个工厂方法就可以完成我们上面的需求。
实现如下:
//工艺选择
interface DesignFactory {
public function getDesgin($flag);
}
//中国工艺工厂方法
class ChinaDesignFactory {
public function getDesgin($flag) {
if ($flag == 'A') {
echo "A";
}
else if($flag == 'B') {
echo "B"
}
}
}
//美国工艺工厂方法
class AmericaDesignFactory {
public function getDesgin($flag) {
if ($flag == 'A') {
echo "America-A";
}
else if($flag == 'B') {
echo "America-B"
}
}
}
//染料选择
interface ColorFactory {
public function getColor($flag);
}
//中国染料选择
class ChinaColorFactory {
public function getColor($flag) {
if ($flag == 'R') {
echo "RED";
}
else if($flag == 'B') {
echo "BLUE"
}
}
}
//美国染料选择
class AmericaColorFactory {
public function getColor($flag) {
if ($flag == 'R') {
echo "America-RED";
}
else if($flag == 'B') {
echo "America-BLUE"
}
}
}
//金属材料选择
interface IngredientFactory {
public function getIngredient($flag);
}
//中国金属材料
class ChinaIngredientFactory {
public function getIngredient($flag) {
if ($flag == '1') {
echo "Ingredient1";
}
else if($flag == '2') {
echo "Ingredient2"
}
}
}
//美国金属材料
class AmericaIngredientFactory {
public function getIngredient($flag) {
if ($flag == '1') {
echo "America-Ingredient1";
}
else if($flag == '2') {
echo "America-Ingredient2"
}
}
}
在上面一共实现了 工艺工厂方法 (ChinaDesignFactory,AmericaDesignFactory),金属材材料工厂方法(ChinaIngredientFactory,AmericaIngredientFactory),染料工厂方法(ChinaColorFactory,AmericaColorFactory)。
这样似乎很好了,如果想要中国工具制造,就需要调用Chinaxxxx。但是,对于使用者来说(都懒),可能都只是想一个接口就可以做所有的事,同时我们并不希望当使用这些接口的人,想要一个中国制造实例时,不小心调用的了AmericaXXX中的一个。也不想使用者过分依赖实例。
怎么办呢?我们是否可以在定义一层更上层的接口。统一一下。既保证尽量少的向外部提供具体实例和接口,也保证中国制造只获取中国有关的实例,美国工具只获取美国有关的实例。
其实想想,不管时工艺工厂方法,材料工厂方法,或者染料工厂方法,都是为工具制造服务的。那么我们就定义一层工具制造接口吧。
interface abstractFactory {
public function Design($flag);
public function Color($flag);
public function Ingredient($flag)
}
//中国制造
class ChinaFactory implements abstractFactory{
public function Design($flag){
$factory = new ChinaColorFactory();
return $factory->getDesgin($flag);
}
public function Color($flag){
$factory = new ChinaColorFactory();
return $factory->getColor($flag)
}
public function Ingredient($flag){
$factory = new ChinaIngredientFactory();
return $factory->getIngredient($flag)
}
}
//美国制造
class AmericaFactory implements abstractFactory{
public function Design($flag){
$factory = new AmericaColorFactory();
return $factory->getDesgin($flag);
}
public function Color($flag){
$factory = new AmericaColorFactory();
return $factory->getColor($flag)
}
public function Ingredient($flag){
$factory = new AmericaIngredientFactory();
return $factory->getIngredient($flag)
}
}
这样,对外的类就 变成了 AmericaFactory 和 ChinaFactory。 同时保证了,中国制造只能获取中国实例,美国只能美国相关的实例。
而这就是今天的主角 抽象工厂模式
优点:
1.将客户和与类的实现分离。让客户依赖接口,只通过抽象接口操作实例----Abstractory
2.易于交换产品系列(抽象工厂用于创建一系列相关或者相互依赖的接口) ---- 中国制造和美国制造可以简单替换
3.它有利于产品的一致性。当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列的对象。这点很重要(中国制造和美国制造是两个系列)
缺点:
难以扩展新种类的产品,因为产品集合一开始确定在AbstractFactory中,新增产品种类,需重新修改原有的抽象类,这可能涉及到子类的修改。比如添加标签打印方式。需要修改abstractFactory, 添加一个抽象方法,用来选择标签打印方式。这就涉及到子类的修改。
以上,我结束了简单工厂方法、工厂方法和抽象工厂方法的学习。
下篇,我将总结简单工厂方法、工厂方法和抽象工厂方法。