定义:抽象工厂模式提供了一种方法,把那些拥有公共主题的工厂组合起来,并且在使用时不需要考虑他们生产的是哪个具体类的对象。
AbstractFactory模式就是用来解决这类问题的:要创建一组相关或者相互依赖的对象。
例如,在游戏开发中,你需要创建不同等级,不同的等级有不同的怪物出现,这样就涉及了产品等级结构与产品族。
先介绍一下产品等级结构与产品族的概念:
概述:该模式是工厂模式的延伸。先介绍一下产品等级结构与产品族的概念,如下图。假设某个软件能够显示方、圆、菱形。本来这几种形状是很朴素的,黑白的,现在用户觉着太丑,换了一套拟人化的皮肤来显示方、圆、菱形。分别是方肘子、圆大头、菱妹妹。一套皮肤就是一个产品族,同一类形状就是一个产品等级结构。言归正传,抽象工厂模式的存在使得高层模块只需要给出具体的产品族和产品等级结构(如拟人、方)这两个参数,就可以得到对应的实例。
核心思想:高层模块只需要知道自己是哪个产品族的,藉此确定具体工厂。再通过具体工厂获取对象的时候不需要知道这个对象是属于哪个具体类的,具体工厂决定使用哪个具体类。
UML类图:
举个例子,一个怪物类有两个怪物,Tigger和 Monkey,Tigger中又分为TiggerA和TiggerB, Monkey中又分为MonkeyA和MonkeyB, 这样A类的怪物属于一个产品族,可以用AFactory创建;B类的怪物属于另一个产品族,可以用BFactory创建。而Tigger和和Monkey分别为两个产品等级。
上代码,代码简单,很容易理解:
首先创建产品类,也就是该列子中的怪物
#ifndef __MONSTER__H__
#define __MONSTER__H__
//老虎类
class TiggerBase {
public:
TiggerBase();
virtual ~TiggerBase();
};
class TiggerA :public TiggerBase {
public:
TiggerA();
~TiggerA();
};
class TiggerB :public TiggerBase {
public:
TiggerB();
~TiggerB();
};
/*
创建猴子系列类
*/
class MonkeyBase {
public:
MonkeyBase();
virtual ~MonkeyBase();
};
class MonkeyA : public MonkeyBase {
public:
MonkeyA();
~MonkeyA();
};
class MonkeyB : public MonkeyBase {
public:
MonkeyB();
~MonkeyB();
};
#endif
#include "Monster.h"
#include <iostream>
using namespace std;
TiggerBase::TiggerBase() {}
TiggerBase::~TiggerBase() {}
TiggerA::TiggerA() { cout << "创建了TiggerA" << endl; }
TiggerA::~TiggerA() {};
TiggerB::TiggerB() { cout << "创建了TiggerB" << endl; }
TiggerB::~TiggerB() {}
MonkeyBase::MonkeyBase() {}
MonkeyBase::~MonkeyBase() {}
MonkeyA::MonkeyA() { cout << "创建了MonkeyA" << endl; }
MonkeyA::~MonkeyA() {}
MonkeyB::MonkeyB() { cout << "创建了MonekyB" << endl; }
MonkeyB::~MonkeyB() {}
然后创建工厂类,包括父类与具体类
#ifndef __MONSTERFACTORY__H__
#define __MONSTERFACTORY__H__
class MonsterFactory {
public:
MonsterFactory();
virtual ~MonsterFactory();
public:
virtual void createTigger() = 0;
virtual void createMonkey() = 0;
};
class AFactory : public MonsterFactory {
public:
AFactory();
~AFactory();
void createTigger();
void createMonkey();
};
class BFactory : public MonsterFactory {
public:
BFactory();
~BFactory();
void createTigger();
void createMonkey();
};
#endif
#include "MonsterFactory.h"
#include "Monster.h"
MonsterFactory::MonsterFactory() {}
MonsterFactory::~MonsterFactory() {}
AFactory::AFactory() {};
AFactory::~AFactory() {};
void AFactory::createTigger() {
new TiggerA();
}
void AFactory::createMonkey() {
new MonkeyA();
}
BFactory::BFactory() {};
BFactory::~BFactory() {};
void BFactory::createTigger() {
new TiggerB();
}
void BFactory::createMonkey() {
new MonkeyB();
}
接下来在main中使用一下:
#include "MonsterFactory.h"
#include <iostream>
int main() {
std::cout << "------------抽象工厂模式---------------" << std::endl;
MonsterFactory* factoryA = new AFactory();
MonsterFactory* factoryB = new BFactory();
std::cout << "AFactory 创建" << std::endl;
factoryA->createMonkey();
factoryA->createTigger();
std::cout << std::endl;
std::cout << "BFactory 创建" << std::endl;
factoryB->createMonkey();
factoryB->createTigger();
}
运行结果如下:
抽象工厂模式的优点与缺点:
优点:
将一系列具有某种共性的对象统一在一起,使得选择提前。例如软件的皮肤只需要在开始的时候做出选择,之后画方画圆的时候都不需要再考虑选择的问题了。
高层模块可以方便地通过更换具体工厂来改变所需创建的产品对象类型。
具体工厂可以方便地更换想要创建的产品类型。
增删产品族十分方便。
缺点:增删产品等级结构十分麻烦。需要产品等级结构足够稳定。
游戏中的使用场景:
游戏难度、游戏阵营。不同级别难度下游戏可以产生不同类型的建筑、英雄以及技能。
AI 战术选择。实现确定好几种可选战术作为产品族,每种战术按照类似海军、空军、陆军作为产品等级结构选择具体兵种进行生产建造。
国际化。用户改变语言环境时,会改变响应的文字显示,音效,图片显示,操作习惯适配等。
皮肤更换或者资源管理。用户选择不同主题的皮肤将会影响图片显示以及动画效果。
屏幕适配。对高、中、低分辨率的移动设备使用不同的显示资源。