抽象工厂简介:
是一种创建对象的方法,当一个类簇的一种派生类对象需要被创建时,只需提供一个接口,并通过参数指定要创建的对象型号,该工厂即可返回该类型对象的指针。
核心:
将客户和生产线分离。
一般实现方法:
- l 工厂存在一个实例,提供N个接口供客户调用,每个接口负责一个类簇;
- l 工厂依赖全部基类和派生类,并为每一个类簇提供一个接口,当存在N个类簇时,提供N个接口;
- l 客户依赖全部基类,如非特殊情况,客户不依赖派生类;
- l 如果需要添加新的类簇,需要修改:工厂生产方法,工厂接口函数,客户的依赖关系。
优点:
- l 访问该工厂的客户只需要知道自己想要的对象的基类和一个型号参数,即可得到正确的对象,操作简单。
- l 分离了基类和具体类,客户只需要依赖基类,不需要依赖于具体的类。
缺点:
- l 客户可能被欺骗,即工厂返回的不是客户想要的类,客户在不依赖具体类的情况下,无法判别真伪;
- l 当客户依赖于具体类的时候,可以通过向下类型转换从而按派生类去访问,但是如果被欺骗的话将会出现转换失败的情况;
- l 扩展新的类簇是,需要添加生产方法,添加接口,修改客户的依赖关系。
图 1 抽象工厂的类图示意图
编程实例:
模拟即时策略游戏中的一方势力的数据结构设计。
其中军队:ArmyList中的对象由抽象工厂模式实现,即:制造坦克和飞机的时候,Camp不需要知道有多少种坦克,他只需要知道坦克类型编号即可生产对应的坦克,飞机同理。
图 2 阵营&兵力模型
代码:
1 #include2 #include 3 #include 4 5 /*** 6 * @author:zanzan101 7 */ 8 9 using namespace std; 10 // 定义枚举类型 11 enum tank_state 12 { 13 TANK_ATTACK, 14 TANK_MOVE, 15 TANK_MOVEATTACK, 16 TANK_GARD, 17 TANK_HOLD 18 }; 19 enum tank_type 20 { 21 GRIZZLYTANK, 22 RHINOHEAVYTANK 23 }; 24 enum airplane_state 25 { 26 AIRPLANE_ATTACK, 27 AIRPLANE_MOVE, 28 AIRPLANE_MOVEATTACK, 29 AIRPLANE_GARD, 30 AIRPLANE_HOLD 31 }; 32 enum airplane_type 33 { 34 BLACKEAGLE, 35 NIGHTHAWK 36 }; 37 // 定义坦克类 38 class Tank 39 { 40 protected: 41 int m_hp; 42 int m_damage; 43 int m_speed; 44 int m_state; 45 int m_type; 46 int m_pos_x; 47 int m_pos_y; 48 bool m_dead; 49 public: 50 Tank(): m_hp(0), m_damage(0), m_speed(0), m_state(TANK_GARD), m_type(0), m_pos_x(0), m_pos_y(0), m_dead(false){} 51 void attack(Tank* target) 52 { 53 target->m_hp -= m_damage; 54 if(target->m_hp < 0) 55 { 56 target->m_hp = 0; 57 target->set_dead(true); 58 } 59 } 60 void set_dead(bool b = false){m_dead = b;} 61 virtual void speaking()=0; 62 }; 63 64 class GrizzlyTank: public Tank 65 { 66 public: 67 GrizzlyTank():Tank() 68 { 69 m_type = GRIZZLYTANK; 70 m_hp = 100; 71 m_damage = 80; 72 m_speed = 20; 73 } 74 void speaking() 75 { 76 cout<< "I'm a Grizzly Tank!" < m_hp -= m_damage;117 if(target->m_hp < 0)118 {119 target->m_hp = 0;120 target->set_dead(true);121 }122 }123 void set_dead(bool b = false){m_dead = b;}124 virtual void speaking()=0;125 };126 127 class BlackEagle: public Airplane128 {129 public:130 BlackEagle():Airplane()131 {132 m_type = BLACKEAGLE;133 m_hp = 60;134 m_damage = 120;135 m_speed = 100;136 m_missle_count = 4;137 }138 void speaking()139 {140 cout<< "I'm a BlackEagle!" < m_tanks;199 vector m_airplanes;200 public:201 ArmyList(){}202 ~ArmyList()203 {204 // 释放指针所指内存空间205 for(int i = 0; i < m_tanks.size(); i++)206 {207 delete m_tanks[i];208 m_tanks[i] = 0;209 }210 vector ().swap(m_tanks);211 212 // 释放指针所指内存空间213 for(int i = 0; i < m_airplanes.size(); i++)214 {215 delete m_airplanes[i];216 m_airplanes[i] = 0;217 }218 vector ().swap(m_airplanes);219 }220 void add_tank(int tank_type, int count=1)221 {222 while(count-- > 0)223 m_tanks.push_back(VehichleFactory::get_tank(tank_type)); // 调用抽象工厂的接口224 }225 void add_airplane(int airplane_type, int count=1)226 {227 while(count-- > 0)228 m_airplanes.push_back(VehichleFactory::get_airplane(airplane_type)); // 调用抽象工厂的接口229 }230 void speaking()231 {232 for(int i = 0; i < m_tanks.size(); i++)233 m_tanks[i]->speaking();234 for(int i = 0; i < m_airplanes.size(); i++)235 m_airplanes[i]->speaking();236 }237 };238 239 class Camp240 {241 private:242 BuildingList m_buildinglist;243 Money m_money;244 ArmyList m_armylist;245 public:246 void do_something()247 {248 // 模拟一些操作行为249 m_armylist.add_tank(GRIZZLYTANK);250 m_armylist.add_tank(RHINOHEAVYTANK, 3);251 m_armylist.add_airplane(BLACKEAGLE, 2);252 m_armylist.add_airplane(NIGHTHAWK);253 m_armylist.speaking();254 }255 };256 257 258 int _tmain(int argc, _TCHAR* argv[])259 {260 Camp camp;261 camp.do_something();262 system("pause");263 return 0;264 }
输出结果:
I'm a Grizzly Tank!I'm a Rhino Heavy Tank!I'm a Rhino Heavy Tank!I'm a Rhino Heavy Tank!I'm a BlackEagle!I'm a BlackEagle!I'm a NightHawk!请按任意键继续. . .