Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
First, it should be noted that the Prototype pattern is not used to gain performance benefits. It’s only used for creating new objects from prototype instances.
Real-world example
Remember Dolly? The sheep that was cloned! Let’s not get into the details but the key point here is that it is all about cloning.
In plain words
Create an object based on an existing object through cloning.
Wikipedia says
The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects.
In short, it allows you to create a copy of an existing object and modify it to your needs, instead of going through the trouble of creating an object from scratch and setting it up.
Programmatic Example
In Java, the prototype pattern is recommended to be implemented as follows. First, create an
interface with a method for cloning objects. In this example, Prototype
interface accomplishes
this with its copy
method.
1public abstract class Prototype<T> implements Cloneable {
2 @SneakyThrows
3 public T copy() {
4 return (T) super.clone();
5 }
6}
Our example contains a hierarchy of different creatures. For example, let’s look at Beast
and
OrcBeast
classes.
1@EqualsAndHashCode(callSuper = false)
2@NoArgsConstructor
3public abstract class Beast extends Prototype<Beast> {
4
5 public Beast(Beast source) {
6 }
7
8}
9
10@EqualsAndHashCode(callSuper = false)
11@RequiredArgsConstructor
12public class OrcBeast extends Beast {
13
14 private final String weapon;
15
16 public OrcBeast(OrcBeast orcBeast) {
17 super(orcBeast);
18 this.weapon = orcBeast.weapon;
19 }
20
21 @Override
22 public String toString() {
23 return "Orcish wolf attacks with " + weapon;
24 }
25
26}
We don’t want to go into too many details, but the full example contains also base classes Mage
and Warlord
and there are specialized implementations for those for elves in addition to orcs.
To take full advantage of the prototype pattern, we create HeroFactory
and HeroFactoryImpl
classes to produce different kinds of creatures from prototypes.
1public interface HeroFactory {
2
3 Mage createMage();
4 Warlord createWarlord();
5 Beast createBeast();
6}
7
8@RequiredArgsConstructor
9public class HeroFactoryImpl implements HeroFactory {
10
11 private final Mage mage;
12 private final Warlord warlord;
13 private final Beast beast;
14
15 public Mage createMage() {
16 return mage.copy();
17 }
18
19 public Warlord createWarlord() {
20 return warlord.copy();
21 }
22
23 public Beast createBeast() {
24 return beast.copy();
25 }
26}
Now, we are able to show the full prototype pattern in action producing new creatures by cloning existing instances.
1 var factory = new HeroFactoryImpl(
2 new ElfMage("cooking"),
3 new ElfWarlord("cleaning"),
4 new ElfBeast("protecting")
5 );
6 var mage = factory.createMage();
7 var warlord = factory.createWarlord();
8 var beast = factory.createBeast();
9 LOGGER.info(mage.toString());
10 LOGGER.info(warlord.toString());
11 LOGGER.info(beast.toString());
12
13 factory = new HeroFactoryImpl(
14 new OrcMage("axe"),
15 new OrcWarlord("sword"),
16 new OrcBeast("laser")
17 );
18 mage = factory.createMage();
19 warlord = factory.createWarlord();
20 beast = factory.createBeast();
21 LOGGER.info(mage.toString());
22 LOGGER.info(warlord.toString());
23 LOGGER.info(beast.toString());
Here’s the console output from running the example.
Elven mage helps in cooking
Elven warlord helps in cleaning
Elven eagle helps in protecting
Orcish mage attacks with axe
Orcish warlord attacks with sword
Orcish wolf attacks with laser
Use the Prototype pattern when a system should be independent of how its products are created, composed, represented and