原文链接:http://gameprogrammingpatterns.com/prototype.html
Prototype(原型)
我第一次听说“Prototype”这个词是在设计模式中。今天我发现大家都在说这个词,但是已经不是在谈设计模式了。我们会在这里展开讨论,但是我也会给你介绍一些别的有趣的地方,以及一些其他的衍生概念。但让我们先领略一遍经典的内容。
原型设计模式、
假设我们在做一款类似《圣铠传奇》的游戏。在英雄的周围会产生很多生物和魔鬼,企图分享他的肉。这些恶心的晚餐伙伴是通过“卵”进入场景的,并且不同的敌人用的是不同的卵。 在这个例子中,我们为每一种怪物创建一个类-Ghost,Demon,Sorcerer等等,像这样:
|
class Monster { // Stuff... }; class Ghost : public Monster {}; class Demon : public Monster {}; class Sorcerer : public Monster {}; |
一个卵的构造函数实例化一个特定的怪物类型。为了支持游戏中所有的怪物,我们简单粗暴得为每一种怪物写一个卵类,构成了这个并行的类结构。

像这样实现他们:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class Spawner { public: virtual ~Spawner() {} virtual Monster* spawnMonster() = 0; }; class GhostSpawner : public Spawner { public: virtual Monster* spawnMonster() { return new Ghost(); } }; class DemonSpawner : public Spawner { public: virtual Monster* spawnMonster() { return new Demon(); } }; |
除非你是按代码行数付费的,否则堆砌这么多垃圾可不时间令人预约的事。大量的类,大量的冗余代码,大量的副本,大量的复制,大量的重复…
原型模式提供了一个解决方案。主要思想是一个对象可以产生其他跟他相似的对象。如果你有一个Ghost,你可以用它产生更多的Ghost。如果你有一个Demon,你可以产生其他Demon。任何一个怪物都可以被当作一个原型怪物,用来产生其他的分身。
为了实现这个,我们提供一个基类,Monster,和一个虚函数clone():
|
class Monster { public: virtual ~Monster() {} virtual Monster* clone() = 0; // Other stuff... }; |
每一个怪物的子类都可以实现一个方法,返回一个跟自己类型状态一模一样的新对象。例如:
|
class Ghost : public Monster { public: Ghost(int health, int speed) : health_(health), speed_(speed) {} virtual Monster* clone() { return new Ghost(health_, speed_); } private: int health_; int speed_; }; |
read more