设计模式03--抽象工厂模式(Abstract Factory)
2019-06-03 本文已影响1人
四月不见
一、简介
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
注意:这里和工厂方法的区别是:一系列(多个),而工厂方法只有一个。
二、类结构
抽象工厂模式结构如下:
角色 | 类别 | 简述 |
---|---|---|
AbstractFactory | 抽象工厂 | 一般是一个抽象类或是接口 |
ConcreteFactory | 具体工厂 | 用来创建一系列具体的产品 |
AbstractProduct | 抽象产品 | 一个抽象类或是接口 |
Product | 具体产品 | 用来创建具体的产品 |
三、UML图
比如,我们需要设计一个绘图工具:
四、类实现
1、抽象产品
图形类接口:
interface Shape{
public function draw();
}
颜色类接口:
interface Color {
public function fill();
}
2、具体产品
具体图形类:
//矩形类
class Rectangle implements Shape {
public function draw() {
echo '插入一个矩形 \n\r';
}
}
//正方形类
class Square implements Shape {
public function draw() {
echo '插入一个正方形 \n\r';
}
}
//圆形类
class Circle implements Shape {
public function draw() {
echo '插入一个圆形 \n\r';
}
}
具体颜色类:
//红色类
class Red implements Color {
public function fill() {
echo '填充红色 \n\r';
}
}
//绿色类
class Green implements Color {
public function fill() {
echo '填充绿色 \n\r';
}
}
//蓝色类
class Blue implements Color {
public function fill() {
echo '填充蓝色 \n\r';
}
}
3、抽象工厂
为 Color 和 Shape 对象创建抽象类来获取工厂。
class interface AbstractFactory {
public function getColor($color);
public function getShape($shape) ;
}
4、具体工厂
//形状工厂类
class ShapeFactory extends AbstractFactory {
public function getShape($shapeType){
if($shapeType == false){
return false;
}
if($shapeType=="circle"){
return new Circle();
} else if($shapeType=="rectangle"){
return new Rectangle();
} else if($shapeType=="square"){
return new Square();
}
return false;
}
public function getColor($color) {
return false;
}
}
//颜色工厂类
class ColorFactory extends AbstractFactory {
public function getShape($shapeType){
return false;
}
public function getColor($color) {
if($color == false){
return false;
}
if($color=="red"){
return new Red();
} else if($color=="green"){
return new Green();
} else if($color=="blue"){
return new Blue();
}
return false;
}
}
5、工厂创造器
创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂。
class FactoryProducer {
public static function getFactory($choice){
if($choice=="shape")){
return new ShapeFactory();
} else if($choice=="color"){
return new ColorFactory();
}
return null;
}
}
6、使用实例
public class Demo {
public static function test() {
//获取形状工厂
$shapeFactory = FactoryProducer::getFactory("SHAPE");
//为形状插入Circle对象
$shape1 = $shapeFactory->getShape("circle");
//调用 Circle 的 draw 方法
$shape1->draw();
//为形状插入Rectangle对象
$shape2 = $shapeFactory->getShape("rectangle");
//调用 Rectangle 的 draw 方法
$shape2->draw();
//获取颜色工厂
$colorFactory = FactoryProducer::getFactory("color");
//获取颜色为 Red 的对象
$color1 = $colorFactory->getColor("red");
//调用 Red 的 fill 方法
$color1->fill();
}
}
Demo::test();
测试结果:
插入一个圆形
插入一个矩形
填充红色
五、特点
1、优点
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
- 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
2、缺点
- 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
- 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。。
3、适用场景
在以下情况下可以考虑使用抽象工厂模式:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。