Design Pattern Prototype, in a nutshell
Disclaimer ⚠️. Even though this pattern belongs to the code smell section in Java, worth knows it and recognize and know what is your purpose.
Below we can see the prototypes of Stormtrooper since for me they’re always equals.
Motivation
Use the Prototype Pattern when a client needs to create a set of objects that are alike or differ from each other only in terms of their state and creating an instance of a such object (e.g., using the “new” keyword) is either expensive or complicated.[7]
Applicability
Excerpt from GOF book,
Use the Prototype pattern when a system should be independent of how its products are created, composed, and represented; and
when the classes to instantiate are specified at run-time, for example, by dynamic loading; or
to avoid building a class hierarchy of factories that parallels the class hierarchy of products; or
when instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state.
Where can I use this pattern?
Based on the lecture, and the motivation this pattern can be used on creating a new set of objects when a new Object is difficult to build them.
Let’s think about, Spring uses the bean context prototype when a stateful is required, then the idea of this pattern could be moved to this annotation. I do not check the Spring’s code, I’m doing an assumption.
Examples
GOF
The diagrams below show how to build and identify in the design phase this pattern.
Hands on
For this hands on, I choose the Git model, based on these references Git-SCM, Astah, and GitHub.
The class Repository has the following data: id, owner, description, visibility (public or private repository), a list of GitObjects and, a list of References, similar to Astah diagram.
Participants
Client → This class represents the client itself. Here using the main method to create an instance of Repository and then using the prototype design pattern, that’s it, calling the prototype method.
Prototype → This interface extends Cloneable and any Concrete Prototype should implement this interface, that allows the clone operation.
If you try to override the method clone that is on Object class and not in Cloneable interface, you will receive a java.lang.CloneNotSupportedException exception.
GitObject as ConcretePrototype → This class implements the interface above and makes feasible this class be prototyped, i.e, cloned. Getters and setters were omitted, but are available on the code repository[8].
GitObject as ConcretePrototype → This class implements the interface Prototype and makes feasible this class be prototyped, i.e, cloned. Getters and setters were omitted, but are available on the code repository[8].
Tests
In order to execute the tests, let’s use JUnit 5 as a test framework.
GitObject → A simple test using the isEqualToComparingFieldByFieldRecursively method from assertj. This method is useful because it compares every field.
Repository → A simple test using the isEqualToComparingFieldByFieldRecursively method from assertj. This method is useful because it compares every field. The createFakeGitObject method is only to generate fake data.
Code
The complete code is available on my GitHub.
Conclusion
This design pattern is useful when creating a new object-based on others is not easier, but as I mentioned in this article start, pay attention to drawbacks brought when the clone is called since the clone is easier to implement than make it programmatically.
References
1 — Gamma Erich, Helm Richard, Johnson Ralph, Vlissides John, Grady Booch. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.
2 — Eric Freeman, Elisabeth Robson. (2020). Head First Design Patterns, 2nd Edition. O’Reilly Media, Inc.
3 — https://www.artima.com/intv/bloch.html#part13
4 — https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
5 — https://astahblog.com/2015/09/08/git-data-model/
6 — Cover image