Prototype is one of the easier to understand design patterns. The intent of
prototype is to create new instances of classes by cloning a prototype
instance, rather than building them from scratch. This is particularly useful
when the initialization of the objects is very expensive and very similar among
the majority of created instances.
Take this for instance, you have some data stored on a remote server. You need
them to initialize 1000 instances of some class during your program runtime.
This data are static and very unlikely to be changed during the runtime of your
application. You see, that downloading the data during initialization in
constructor is pretty ineffective. Design like that would lead to exactly 999
pointless connections to the server and a lot of unnecessary network traffic,
which is a gigantic waste of resources and time. If you use prototype instead,
the application will download the data just once and the 1000 more instances
will be cloned from the first one, saving us all the trouble.
There are three participants in the prototype pattern:
Client - creates a new object by asking a prototype to clone itself.
Prototype - declares an interface for cloning itself.
Concrete Prototype - implements the operation for cloning itself.
You also need a place where all the prototypes will be stored. A good practice
is using a factory class that will cover the initial prototype setup and
will handle the cloning operations. This might remind you of the abstract
factory design pattern. This is because they both
are creational patterns and can be used to achieve the same behavior. The thing
about prototype is that, you can dynamically change the prototype instance
during the runtime and begin constructing something completely different with
the same factory without sub-classing it.
Another way of dynamic handling a lot of prototype instances is prototype
manager. A class that stores a pool of prototypes and makes decisions on
which one to instantiate based on some parameters. This is particularly useful
when the amount of prototypes isn’t fixed.
Now, let’s proceed to the code examples. I went with the first variant – a
factory class for storing the prototypes.