创建型模式抽象实例化过程。帮助一个系统独立于如何创建、组合和表示它的那些对象。
以构建一个房间探索游戏的设计为例:
未引入创建型模式前,对于一个完整的探索系统,需要由用户不断地调用各个组件的构造函数,从而代码渐渐复杂起来。代码复杂且未经设计的最大的后果便是维护困难。现在想要给某一套组件换成另外一套组件,带来的后果是所有的用户代码都要进行修改。这个过程是有一定风险的。
解决办法是一定存在的,现在引入几个创建型模式:
传入工厂对象作参数来指定创建房间、墙壁和门的类型:Abstract Factory 抽象工厂
调用虚函数而不是构造函数来创建(让子类来决定实例化那个类):Factory Method 工厂方法
引入传递对象并且通过这个对象增加房间、墙壁和门:Builder 生成器
原型的房间、墙壁和门对象参数化,它拷贝并将这些对象增加到迷宫中:Prototype 原型
对于每一种Factory而言每个程序里仅有一个:Singleton 单例
Abstract Factory最擅长解决替换成套组件的问题,它通过传入对象来确定内部实例化的类,取消对类名的硬编码。
请看示意图:
最原始的工厂可以构造PartA PartB。如今使用Part' PartA' PartB'。容易想到使用一个继承的结构。让Part'继承Part,把Part中实例化PartA PartB的函数声明为virtual,从而可以在Part'中重写实例化函数,这样调用时虽然用的还是PartA的名字,但是事实上调用的是PartA'的内容,实现了代码重用。
Client无需了解使用的是PartA0还是PartA1,一切都在构造Factory时使用的是PartFactory还是SpecialPartFactory。
代码示例:
#include<stdio.h>
class PartA {
int len;
public:
PartA(int n) { len = n; }
virtual ~PartA() {}
};
class PartA1 : public PartA {
int len;
int item;
public:
PartA1(int n):PartA(n) { len = n; }
};
class PartB {
int id;
PartA* rList[100];
public:
PartB(int i) { id = i; }
virtual ~PartB() {
//析构内部内容
}
};
class PartB1 : public PartB {
int id;
int item;
public:
PartB1(int i, int it) :PartB(i) { id = i; item = it; }
};
class Maze {
public:
Maze() {};
~Maze() {
//析构所有Maze内包含的部件
//最后析构delete maze
}
private:
PartB* rlist[100];
};
//Abstract Factory
class MazeFactory {
public:
MazeFactory(){}
virtual Maze* MakeMaze() const
{
printf("Maze Start!");
return new Maze;
};
virtual PartA* MakePartA(int l) const
{
printf("PartA %d!", l);
return new PartA(l);
}
virtual PartB* MakePartB(int i) const
{
printf("PartB %d!", i);
return new PartB(i);
}
};
class UnexpectedMazeFactory : public MazeFactory {
public:
UnexpectedMazeFactory() {};
virtual PartA* MakePartA(int l) const
{
printf("Item PartA %d!", l);
return new PartA(l);
}
virtual PartB* MakePartB(int i) const
{
printf("Special PartB %d with item %d!", i, GetSpecial());
return new PartB1(i, GetSpecial());
}
protected:
int GetSpecial() const { return 1; }; //返回一个值
};
class Game {
public:
Maze* CreateMaze(MazeFactory& factory) {
Maze* myMaze = factory.MakeMaze();
PartB* r1 = factory.MakePartB(10);
PartB* r2 = factory.MakePartB(5);
PartA* a3 = factory.MakePartA(1);
return myMaze;
}
private:
Maze* m;
};
int main() {
Game myGame;
UnexpectedMazeFactory factory;
Maze* myMaze = myGame.CreateMaze(factory);
getchar();
}
参考书籍:《设计模式 可复用面向对象软件的基础》Erich Gamma等