创建型模式
抽象工厂模式,从工厂两个字上就可以看出这种模式包含一种生产的概念在里面,我们直接从一个例子来讲解抽象模式吧。
比如说,我们现在要做一个代码编辑器,这个代码编辑器支持c++、javascript、 python等等语言,同时也支持各样的编辑器窗体布局、主题样式、字体样式。
首先我们定义抽象类,每个抽象元素里面都有一些类功能相关的抽象接口,这里为了方便浏览,没有列出来了
// 抽象元素
class Code {};
class Theme {};
class Text {};
class Layout {};
// 抽象工厂
class Factory {
public:
virtual Theme* createTheme() = 0;
virtual Code* createCode() = 0;
virtual Text* createText() = 0;
virtual Layout* createLayout() = 0;
};
下面则是cpp编辑页相关功能的具体实现
// cpp
class CppCode : public Code {};
class CppTheme : public Theme {};
class CppText : public Text {};
class CppLayout : public Layout {};
class CppFactory : public Factory {
public:
Theme* createTheme() {
return new CppTheme();
}
Code* createCode() {
return new CppCode();
}
Text* createText() {
return new CppText();
}
Layout* createLayout() {
return new CppLayout();
}
};
// Java
class JavaCode : public Code {};
class JavaTheme : public Theme {};
class JavaText : public Text {};
class JavaLayout : public Layout {};
class JavaFactory : public Factory {
public:
Theme* createTheme() {
return new JavaTheme();
}
Code* createCode() {
return new JavaCode();
}
Text* createText() {
return new JavaText();
}
Layout* createLayout() {
return new JavaLayout();
}
};
下面就是具体的使用了,CodeEditPage就是代码编辑页的展示框架了,可以看出,CodeEditPage与JavaFactory、CppFactory没有直接关系,而且JavaFactory和CppFactory也相对独立,后续如果需要新增一个PythonFactory的话,我们只需要单独实现一套PythonFactory的就可以了。
// 代码编辑页
class CodeEditPage {
public:
bool init(Factory* factory) {
theme_ = factory->createTheme();
code_ = factory->createCode();
text_ = factory->createText();
layout_ = factory->createLayout();
return true;
}
private:
Theme* theme_;
Code* code_;
Text* text_;
Layout* layout_;
};
int main () {
// 创建c++工程和java工厂
Factory* javaFactory = new JavaFactory();
Factory* cppFactory = new CppFactory();
// cpp代码编辑页
CodeEditPage cppCodeEdit;
cppCodeEdit.init(cppFactory);
// java代码编辑页
CodeEditPage javaCodeEdit;
javaCodeEdit.init(javaFactory);
// 循环
while (true) {
...
}
delete cppFactory;
delete javaFactory;
return 0;
}
下面是具体类图
总结
抽象工厂模式具有很好的解耦合效果,非常适用于产品族相关的业务设计,它具有非常方便的横向扩展(例如新增一个PythonFactory),但是纵向扩展(比如扩展一个背景Backgroud元素)非常麻烦,改动会非常大。