设计模式学习笔记(开篇)-抽象工厂 工厂模式 简单工厂(3)

继续上篇 设计模式学习笔记(开篇)-抽象工厂 工厂模式 简单工厂(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, 添加一个抽象方法,用来选择标签打印方式。这就涉及到子类的修改。

以上,我结束了简单工厂方法、工厂方法和抽象工厂方法的学习。

下篇,我将总结简单工厂方法、工厂方法和抽象工厂方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值