zoukankan      html  css  js  c++  java
  • 学习设计模式系列之三:抽象工厂

    抽象工厂简介:

    是一种创建对象的方法,当一个类簇的一种派生类对象需要被创建时,只需提供一个接口,并通过参数指定要创建的对象型号,该工厂即可返回该类型对象的指针。

    核心:

             将客户和生产线分离。

    一般实现方法:

    • l  工厂存在一个实例,提供N个接口供客户调用,每个接口负责一个类簇;
    • l  工厂依赖全部基类和派生类,并为每一个类簇提供一个接口,当存在N个类簇时,提供N个接口;
    • l  客户依赖全部基类,如非特殊情况,客户不依赖派生类;
    • l  如果需要添加新的类簇,需要修改:工厂生产方法,工厂接口函数,客户的依赖关系。

    优点:

    • l  访问该工厂的客户只需要知道自己想要的对象的基类和一个型号参数,即可得到正确的对象,操作简单。
    • l  分离了基类和具体类,客户只需要依赖基类,不需要依赖于具体的类。

    缺点:

    • l  客户可能被欺骗,即工厂返回的不是客户想要的类,客户在不依赖具体类的情况下,无法判别真伪;
    • l  当客户依赖于具体类的时候,可以通过向下类型转换从而按派生类去访问,但是如果被欺骗的话将会出现转换失败的情况;
    • l  扩展新的类簇是,需要添加生产方法,添加接口,修改客户的依赖关系。

     

    图 1 抽象工厂的类图示意图

    编程实例:

    模拟即时策略游戏中的一方势力的数据结构设计。

    其中军队:ArmyList中的对象由抽象工厂模式实现,即:制造坦克和飞机的时候,Camp不需要知道有多少种坦克,他只需要知道坦克类型编号即可生产对应的坦克,飞机同理。

     

    图 2 阵营&兵力模型

    代码:

      1 #include <iostream>
      2 #include <vector>
      3 #include <stdlib.h>
      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!" <<endl;
     77     }
     78 };
     79 
     80 class RhinoHeavyTank: public Tank
     81 {
     82 public:
     83     RhinoHeavyTank():Tank()
     84     {
     85         m_type = RHINOHEAVYTANK;
     86         m_hp = 200;
     87         m_damage = 50;
     88         m_speed = 40;
     89     }
     90     void speaking()
     91     {
     92         cout<< "I'm a Rhino Heavy Tank!" <<endl;
     93     }
     94 };
     95 
     96 // 定义空军类
     97 class Airplane
     98 {
     99 protected:
    100     int m_hp;
    101     int m_damage;
    102     int m_speed;
    103     int m_state;
    104     int m_type;
    105     int m_pos_x;
    106     int m_pos_y;
    107     int m_missle_count;
    108     bool m_fly;
    109     bool m_dead;
    110 public:
    111     Airplane(): 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_missle_count(0), m_fly(false), m_dead(false){}
    112     void attack(Airplane* target)
    113     {
    114         if(m_missle_count == 0)
    115             return;
    116         target->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 Airplane
    128 {
    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!" <<endl;
    141     }
    142 };
    143 
    144 class NightHawk: public Airplane
    145 {
    146 public:
    147     NightHawk():Airplane()
    148     {
    149         m_type = NIGHTHAWK;
    150         m_hp = 40;
    151         m_damage = 80;
    152         m_speed = 160;
    153         m_missle_count = 1;
    154     }
    155     void speaking()
    156     {
    157         cout<< "I'm a NightHawk!" <<endl;
    158     }
    159 };
    160 
    161 // 定义生产线
    162 class VehichleFactory
    163 {
    164 public:
    165     // 定义抽象工厂对客户开放的接口
    166     static Tank* get_tank(int tank_type)
    167     {
    168         if(GRIZZLYTANK == tank_type)
    169             return new GrizzlyTank();
    170         else if(RHINOHEAVYTANK == tank_type)
    171             return new RhinoHeavyTank();
    172     }
    173 
    174     // 定义抽象工厂对客户开放的接口
    175     static Airplane* get_airplane(int airplane_type)
    176     {
    177         if(BLACKEAGLE == airplane_type)
    178             return new BlackEagle();
    179         else if(NIGHTHAWK == airplane_type)
    180             return new NightHawk();
    181     }
    182 };
    183 class BuildingList
    184 {
    185     //
    186 };
    187 
    188 class Money
    189 {
    190     //
    191 };
    192 
    193 class Camp;
    194 class ArmyList
    195 {
    196     friend Camp;
    197 private:
    198     vector<Tank*> m_tanks;
    199     vector<Airplane*> 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<Tank*>().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<Airplane*>().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 Camp
    240 {
    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!
    请按任意键继续. . .
  • 相关阅读:
    [堆栈]Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈
    [TI-DSP]sysbios的swi
    [库函数]动态库和静态库优缺点比较
    [S32K]GPIO使用
    [S32K]FreeRTOS使用
    [IC]浅谈嵌入式MCU软件开发之中断优先级与中断嵌套
    [S32K144]多通道ADC使用
    三天搭建博客,包括文章迁移
    网站优化的艺术与科学之实战
    网站优化的艺术与科学之工具和基础知识
  • 原文地址:https://www.cnblogs.com/zanzan101/p/3404213.html
Copyright © 2011-2022 走看看