Design Pattern Factory Method, in a nutshell
Sometimes everything we want is the simplest way to create an object, and this object helps us to achieve this goal. This article is based on the Gang Of Four book and uses JUnit5 to execute the tests.
Motivation
Frameworks use abstract classes to define and maintain relationships between objects. A framework is often responsible for creating these objects as well.[1]
Applicability
Handles object creation and encapsulates it in a subclass. This decouples the client code in the superclass from the object code in this subclass.[5]
Where can I use this pattern?
This pattern can be used based on motivation and applicability sections, moreover to make system design well.
Examples
The first example is a GOF diagram, where the 4 elements[1] are declared below.
- Product[1] → Defines the interface of objects the factory method creates.
- Concrete Product[1] → Implements the Product interface.
- Creator[1] → Declares the factory method, which returns an object of type Product. Creator may also define a default implementation of the factory method that returns a default ConcreteProduct object.
- Concrete Creator[1] → Overrides the factory method to return an instance of a ConcreteProduct.
GOF
Example — Hands on
To explain this pattern, the goal of this pattern will create cloud documents given a provider. There are three providers, Google, Microsoft, and Apple, and the default document will be a Google Doc.
The default document is declared on the abstract Application <Creator> class. This class doesn’t have logic to create it when the method is called a new instance of Google Doc is created.
On the other hand, the MyApplication <Concrete creator> class is responsible for overrides the method, and based on enum value returns a new instance.
The interface Document <Product> has the behavior required for a document and not all documents will implement these behaviors, which will be covered in the test section.
Just to reinforce, the classes GoogleDoc, PagesDocument, and WordDocument represents the <ConcreteProduct>.
Application
MyApplication
CloudDocumentProvider
Document
GoogleDoc
PagesDocument
WordDocument
Tests
This section will be explored how to test this pattern and how to handle exceptions and more.
CloudDocumentProviderTest
The first test is an Enum test. Using JUnit5 this is an easy piece, see below. Given a list of values, check if the enum has these values.
GoogleDocTest
In this test, there are different ways to handle/expected an exception. The methods rename/delete shows how it is.
PagesDocument
This test brings the assertAll. The assertAll should be used when the verification should be executed in all asserts, even a failed assert happens.
WordDocumentTest
This test uses on delete method the method catchThrowable. This method captures the exception and then makes any kind of assertion.
MyApplicationTest
In the MyApplication test, the good part of JUnit 5 is about the Parameterized test. Given cloud providers, a type of document is expected.
Conclusion
The use of the factory method is good and use the 4 elements is even better, since the patterns are a way to have an understandable design.
Code
The complete code is available in my GitHub.
References
1 — https://learning.oreilly.com/library/view/design-patterns-elements/0201633612/ch03.html
2 — https://en.wikipedia.org/wiki/Factory_method_pattern#Java
4 — Cover image — https://pixabay.com/pt/users/michaelgaida-652234/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2267789
5 — Head First Design Patterns