Prototype Design Pattern
Implementing Prototype Design Pattern like a boss and then laughing it off.
Bonus: coool way of spawning arrays of objects from a prototypical instance (check spawnMonsterArray
).
The prototype pattern is a creational software design pattern, that is used when the type of object(s) to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to:
- avoid subclasses of an object creator, like the factory pattern does
- avoid the inherent cost of creating a new object in the standard way (like using
new
) when it can be prohibitively expensive for a given application
Design
- define an abstract
Prototype
class with aclone()
method that returns a copy of itself - create subclasses of
Prototype
. These will be the concrete types. Implement theclone
method - create a
Spawner
/Factory
class with a privatePrototype
pointer (sort of like the Queen bee who never leaves the hive) and aspawnObject()
method. The Spawner class resembles aPrototype
factory function. The spawnObject() method simply calls clone on its prototype object and returns it. - in the
Spawner
class call the prototype'sclone
method to return a copy of the prototype object based on the concrete subobject.
Notice there is a 1-to-1 relationship between a prototype and a factory/spawner. So create as many prototypical objects and their respective factory/spawner objects as the concrete subclasses you want to create.
Usage
- create the prototype(s):
std::unique_ptr<Monster> skeletonPrototype = std::make_unique<Skeleton>();
- create the factory/spawner:
std::unique_ptr<MonsterSpawner> skeletonFactory = std::make_unique<MonsterSpawner>( skeletonPrototype.get() );
- spawn a copy of the prototype object using the spawner:
std::unique_ptr<Monster> skeleton = skeletonFactory->spawnMonster();
- or spawn multiple copies:
auto skeletons = spawnMonsterArray<Skeleton>( skeletonFactory.get(), 10 );
The tricky aspect of this pattern in C++ is memory management & ownership of the objects. Thankfully, with C++11 onwards we have smart pointers and they can alleviate a large part of that burden. Still you have to make careful considerations concerning ownership. Create the prototypes as unique_ptr
s, create the arrays/vectors as owners. On the other hand, the factories don't need to own anything, they simply make use of the passed pointer to do their thing. Give the code a careful read.
Prototype objects can be added and removed at run-time. One neat aspect about this pattern is that it doesn't just clone
the class of the prototype, it clones its state too. This means we could make a spawner for fast ghosts, weak ghosts, or slow ghosts just by creating an appropriate prototype Ghost object.
I used Windows and Visual Studio 2017 to build the project.
Github
Github repository link. Snag up the code now!