游戏编程模式之原型模式

版权声明:未经作者允许不可转载 https://blog.csdn.net/qq_38134452/article/details/88715436

“使用特定原型实例来创建特定种类的对象,并通过拷贝原型来创建新的对象”(摘自《游戏编程模式》)

  • 原型:同属于某一父类的各种类
  • 拷贝:同一种类或统一父类的子类实例的初始化可以利用统一的生成器来生成实例

实例:生成敌人

在例子中,我们需要在游戏中生成三种敌人。他们分别书幽灵、恶魔、术士。

  • 最白痴的做法:平行化的类层次结构
    class Monster
    {
        //……
    };
    
    //三类恶魔
    class Ghost    : public Monster{}
    class Demon    : public Monster{}
    class Sorcerer : public Monster{}
    
    //生成器
    class Spawner
    {
        public:
          virtual ~Spawner() {}
          virtual Monster* spawnMonster() = 0;
        
    };
    
    //三类生成器
    class Ghost : public Spawner
    {
        public:
          virtual Monster* spawnMonster()
          {
              return new Ghost();
          }
    }
    ……
    

平行类结构

  • 原型模式提供了一种解决方案。核心思想是一个对象可以生成与自身相似的其他对象
    class Monster
    {
        public:
          virtual ~Monster()        {}
          virtual Monster* clone()  {}
    };
    
    class Ghost : public Monster
    {
        public:
          Ghost(int health,int speed) : m_Health(health),m_Speed(speed) {}
          virtual Monster* clone()
          {
              return new Ghost(m_health,m_Speed);
          }
          
        private:
          int m_Health;
          int m_Speed;
    }
    
    //生成器
    class Spawner
    {
        public:
          Spawner(Monster* prototype) : m_Prototype(prototype)  {}
          Monster* spawnMonster()
          {
              return m_Prototype->clone();
          }
        
        private:
        Monster* m_Prototype;
    }
    
    //Use
    Monster* ghostPrototype = new Ghost(15,3);
    Spawner* ghostSpawner   = new Spawner(ghostPrototype);
    Monster* newOne=ghostSpawner -> spawnMonster();
    

这里我遇到了一个疑惑:为什么Monster* 的变量可以指向一个子类的实例。按道理来说,父类指针指向子类的实例,则指针只可访问父类与子类的公共部分才对。查查资料,才发现我忘了虚函数的意义就在于解决这个问题。一定要学好C++。

  • 除了将生成器设为一个类,我们还可以运用函数指针来去实现。它的意义在于,这样的设计使得每个怪物类只要包含孵化函数指针即可。
    //定义一个函数用来生成幽灵
    Monster* spawnGhost()  //孵化函数
    {
        return new Ghost();
    }
    
    typedef Monster* (*SpawnCallback)();  //函数指针
    
    class Spawner
    {
        public:
          Spawner(SpawnCallback spawn) : m_Spawn(spawn){}
          Mosnter* spawnMonster() {return m_Spawn() ; }
          
        private:
          SpawnCallback m_Spawn;    
    }
    
    //Use 
    Spawner* ghostSpawner =new Spawner(spawnGhost);
    Ghost* newOne = ghostSpawn -> spawnMonster();
    
  • 使用模板类
    class Spawner
    {
        public:
          virtual ~Spawner() {}
          virtual Monster* spawnMonster() = 0;
    }
    
    template <class T>
    class SpawnerFor : public Spawn
    {
        public:
          virtual Monster* spawnMonster()
          {
              return new T();
          }
    }
    

其他

  • 深拷贝与浅拷贝的概念
    • 深拷贝:数值型字段和引用型字段是完全拷贝的。克隆体与原型是独立、无联系的。
    • 浅拷贝:数值型字段拷贝,而引用型字段仅仅拷贝“引用部分”,也就是说和原型公用一个引用变量,当原型改变时,克隆体的引用变量也会跟着改变
    • 由于原型模式的核心就是拷贝原型,因此要区分这两种拷贝方式
  • 书中在这一章节更多的讲述了其它语言原型模式的体现,这里不再记录,有兴趣可以看原书。

知识点、图片全部源于《Game Programming Patterns》,中文名《游戏编程模式》

猜你喜欢

转载自blog.csdn.net/qq_38134452/article/details/88715436