1. 说明
从名称就可以看出来,这个模式与工厂模式肯定有非常大的联系,事实上也确实如此。在工厂模式的示例中看到不同种类的产品会有对应的不同的工厂类,应用程序在使用这些类时要分别创建一个该类的实例,在有很多产品类别的情况下,开放给应用程序的接口也会过多,这在统一接口时会造成一些不必要的麻烦。而抽象工厂模式就针对这种情况,对工厂类再进行了另一层封装,使得即使有多种不同类的产品,暴露给应用程序的接口仍然只有一个。
2. 抽象工厂模式说明
什么是抽象工厂模式
抽象工厂模式同工厂模式一样也属于创建型模式,它在工厂模式的基础上围绕一个抽象工厂去创建不同的工厂。在抽象工厂模式中,接口负责创建不同类型的工厂,而对应用层屏蔽了相关工厂的类型。
意图
提供一个接口以创建一系列相关或相互依赖的对象,而无须指定它们具体的类。
适用的场合
- 一个系统要独立于它的产品的创建、组合和表示;
- 一个系统要由多个产品系列中的一个来配置;
- 要强调一系列相关的产品对象的设计以便进行联合使用;
- 提供一个产品类库,但只想显示它们的接口而不是实现。
优点
屏蔽了不同工厂类的具体实现;使用同一接口创建多种不同工厂类;
缺点
产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
3. 示例说明
3.1 框架
这里采用与上一篇类似的程序去说明抽象工厂模式的设计框架,如下图所示:
从上图可以看出,基本与工厂模式相同,区别在于抽象工厂模式将工厂类(ShapeFactory和ColorFactory)再进行了一次封装,包含到了抽象工厂类AbstractFactory中,这就使得原有的工厂类不再直接暴露在应用程序demo中,而是通过AbstractFactory来创建不同种类的工厂。
3.2 代码实现
Rectangle.h,Square.h, Circle.h, Shape.h, Red.h, Blue.h, Green.h和Color.h与之前工厂模式中的代码相同。
AbstractFactory.h
#ifndef __ABSTRACTFACTORY__
#define __ABSTRACTFACTORY__
#include <string>
#include "Shape.h"
#include "Color.h"
using namespace std;
class AbstractFactory{
public:
virtual Color *GetColor(string color) = 0;
virtual Shape *GetShape(string shape) = 0;
};
class ShapeFactory : public AbstractFactory{
public:
ShapeFactory(){};
Shape *GetShape(string shapeType);
Color *GetColor(string color);
};
class ColorFactory : public AbstractFactory{
public:
ColorFactory(){};
Shape *GetShape(string shapeType);
Color *GetColor(string color);
};
#endif
AbstractFactory.cpp
#include <cstddef>
#include <string>
#include "Circle.h"
#include "Rectangle.h"
#include "Square.h"
#include "Red.h"
#include "Green.h"
#include "Blue.h"
#include "AbstractFactory.h"
Shape *ShapeFactory::GetShape(string shapeType)
{
string str1 = "Circle";
string str2 = "Rectangle";
string str3 = "Square";
if (shapeType == str1){
return new Circle();
}else if (shapeType == str2){
return new Rectangle();
}else if (shapeType == str3){
return new Square();
}
return NULL;
}
Color *ShapeFactory::GetColor(string color)
{
return NULL;
}
Shape *ColorFactory::GetShape(string shapeType)
{
return NULL;
}
Color *ColorFactory::GetColor(string color)
{
string str1 = "Red";
string str2 = "Green";
string str3 = "Blue";
if (color == str1){
return new Red();
}else if (color == str2){
return new Green();
}else if (color == str3){
return new Blue();
}
return NULL;
}
FactoryProducer.h
#ifndef __FACTORYPRODUCER__
#define __FACTORYPRODUCER__
#include <string>
#include "AbstractFactory.h"
class FactoryProducer{
public:
FactoryProducer(){};
AbstractFactory *getFactory(string choice);
};
#endif
FactoryProducer.cpp
#include <string>
#include "FactoryProducer.h"
AbstractFactory *FactoryProducer::getFactory(string choice)
{
string str1 = "Shape";
string str2 = "Color";
if (choice == str1){
return new ShapeFactory();
}else if (choice == str2){
return new ColorFactory();
}
return NULL;
}
demo.cpp
#include "FactoryProducer.h"
int main(int argc, char **argv)
{
FactoryProducer fp;
AbstractFactory *ShapeFactory = fp.getFactory("Shape");
Shape *shape1 = ShapeFactory->GetShape("Circle");
shape1->draw();
Shape *shape2 = ShapeFactory->GetShape("Rectangle");
shape2->draw();
Shape *shape3 = ShapeFactory->GetShape("Square");
shape3->draw();
AbstractFactory *ColorFactory = fp.getFactory("Color");
Color *color1 = ColorFactory->GetColor("Red");
color1->fill();
Color *color2 = ColorFactory->GetColor("Green");
color2->fill();
Color *color3 = ColorFactory->GetColor("Blue");
color3->fill();
return 0;
}
3.3 编译
g++ *.cpp -o demo
3.4 运行
结果如下:
$ ./demo
Inside Circle::draw()
Inside Rectangle::draw().
Inside Square::draw().
Inside Red::fill()
Inside Green::fill()
Inside Blue::fill()
4. 抽象工厂模式与工厂模式的区别
工厂方法模式 | 抽象工厂模式 |
---|---|
针对的是一个产品等级结构 | 针对的是面向多个产品等级结构 |
一个抽象产品类 | 多个抽象产品类 |
可以派生出多个具体产品类 | 每个抽象产品类可以派生出多个具体产品类 |
一个抽象工厂类,可以派生出多个具体工厂类 | 一个抽象工厂类,可以派生出多个具体工厂类 |
每个具体工厂类只能创建一个具体产品类的实例 | 每个具体工厂类可以创建多个具体产品类的实例 |
参考资料
《设计模式 可复用面向对象软件的基础》
抽象工厂模式—菜鸟教程