82
Прототип (Prototype) —
Паттерны программирования игр
int speed_;
};
Как только все наши монстры смогут поддерживать
эту функцию, нам больше не нужен будет класс спауна
для каждого класса монстров. Мы объявим всего один:
class Spawner
{
public:
Spawner(Monster* prototype)
: prototype_(prototype)
{}
Monster* spawnMonster()
{
return prototype_->clone();
}
private:
Monster* prototype_;
};
Он изначально содержит скрытого от нас монстра,
чья единственная цель — служить шаблоном для спауна
и породить больше себе подобных (рис. 5.2). Он прямо как
пчелиная матка, которая никогда не покидает свой улей.
Рис. 5.2.
Спаун, содержащий прототип
Чтобы создать спаун призраков, мы создаем прото-
типный экземпляр призрака, а затем создаем спаун, ко-
торый поддерживает этот прототип:
Паттерны программирования игр
— Другой взгляд на паттерны проектирования
83
Monster* ghostPrototype = new Ghost(15, 3);
Spawner* ghostSpawner = new Spawner(ghostPrototype);
Тонкость этого паттерна заключается в том, что он
не просто клонирует класс прототипа, он также клони-
рует его
состояние
. То есть мы могли бы создать спаун
для быстрых призраков, слабых призраков или медлен-
ных призраков, просто сделав соответствующий прото-
тип призрака.
Я нахожу что-то элегантное и одновременно удиви-
тельное в этом паттерне. Я не могу себе представить,
способен ли я придумать подобный ход, но я и не могу
вообразить, как бы я
без
него обходился.
Так как это работает?
Ну, нам не нужно создавать отдельный класс спауна для
каждого монстра, это уже хорошо. Но нам
нужно
реали-
зовать
clone()
в каждом классе монстров. А такая за-
дача потребует не меньше кода, чем создание отдельных
классов спауна.
Есть и подводные камни, с которыми вы столкне-
тесь, пытаясь написать правильный
clone()
. Создается
глубокий клон или поверхностный? Другими словами,
если демон держит вилы, будет ли клон демона держать
копию вил?
Кроме того, это явно не то решение, которое сэконо-
мит нам много кода в приведенной и, будем честны, на-
думанной проблеме: по факту она действительно
наду-
манная
. Нам следовало принять как должное наличие
отдельных классов для каждого вида монстров. Сей-
час большинство игровых движков реализуются совсем
не
так.
Большинство из нас через тернии пришли к тому, что
управление иерархией больших классов — настоящая
боль. Поэтому мы используем такие паттерны, как Ком-
понент (Component) (с. 272) и Объект типа (Type Object)
(с. 248), для моделирования различных типов объектов
без необходимости создания для каждого своего отдель-
ного класса.
Do'stlaringiz bilan baham: |