Welcome back! We have already covered the Singleton pattern and how it ensures a class has only one instance. Now, let's dive into another essential creational design pattern: the Factory Method pattern. This lesson will guide you through understanding the Factory Method pattern, a powerful tool used to define an interface for creating an object but allows subclasses to alter the type of objects that will be created.
In this lesson, you'll gain a solid understanding of the Factory Method pattern in Java. We will focus on:
WordDocument
and ExcelDocument
) and generating their instances via the factory method.The Factory Method pattern is a creational design pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created. Instead of calling a constructor directly to create an object, the client calls a factory method defined by an abstract class or interface, which delegates the process to derived classes. This approach promotes loose coupling and adheres to the Open/Closed Principle, allowing a system to be extended without modifying existing code.
We'll walk through a code example involving Document
, WordDocument
, and ExcelDocument
classes, managed by a DocumentFactory
class.
First, we define an abstract class for our documents.
Java1public abstract class Document { 2 // Abstract method to be implemented by concrete document types 3 public abstract void open(); 4}
The Document
abstract class declares an abstract method open
that all document types must implement. This provides a common contract for all documents.
We create two concrete implementations of the Document
class, WordDocument
and ExcelDocument
.
Java1public class WordDocument extends Document { 2 @Override 3 public void open() { 4 System.out.println("Opening Word Document."); 5 } 6} 7 8public class ExcelDocument extends Document { 9 @Override 10 public void open() { 11 System.out.println("Opening Excel Document."); 12 } 13}
WordDocument
and ExcelDocument
classes extend the Document
class, thereby providing specific behavior for opening Word and Excel documents respectively.
Next, we create a factory class that provides a method to create instances of Document
.
The factory class encapsulates the logic for creating various types of documents without exposing the creation logic to the client. This ensures that the client code doesn't need to know the details of how the documents are created. Instead, it simply calls the factory method and receives the appropriate document instance.
Java1public class DocumentFactory { 2 // Enum to define supported document types 3 public enum DocumentType { 4 WORD, EXCEL 5 } 6 7 // Factory method to create documents based on the type 8 public static Document getDocument(DocumentType type) { 9 switch (type) { 10 case WORD: 11 return new WordDocument(); 12 case EXCEL: 13 return new ExcelDocument(); 14 default: 15 throw new IllegalArgumentException("Unknown document type: " + type); 16 } 17 } 18}
The DocumentType Enum:
WORD
and EXCEL
). You can easily extend this enum to include additional document types in the future, making the system flexible and scalable.The getDocument Method:
DocumentType
as a parameter and returns an instance of the corresponding document class.switch
statement checks the provided document type and creates an instance of WordDocument
or ExcelDocument
accordingly.IllegalArgumentException
. This guards against invalid input, ensuring robustness in your code.To complete our understanding, let's see how to use the Factory Method pattern via a main method. This will help you see how the abstract factory and concrete factory classes work together to create and manage different types of documents.
Java1public class Main { 2 public static void main(String[] args) { 3 // Create a Word document using the factory method 4 Document wordDoc = DocumentFactory.getDocument(DocumentFactory.DocumentType.WORD); 5 wordDoc.open(); // Outputs: Opening Word Document. 6 7 // Create an Excel document using the factory method 8 Document excelDoc = DocumentFactory.getDocument(DocumentFactory.DocumentType.EXCEL); 9 excelDoc.open(); // Outputs: Opening Excel Document. 10 } 11}
In the main
method:
getDocument
method of DocumentFactory
with DocumentType.WORD
to instantiate a WordDocument
.open
method on the WordDocument
instance to demonstrate its functionality.Similarly:
getDocument
method of DocumentFactory
with DocumentType.EXCEL
to instantiate an ExcelDocument
.open
method on the ExcelDocument
instance to demonstrate its functionality.By following these steps and running the main method, you can observe how the Factory Method pattern allows the creation of document objects without needing to know their specific types at compile-time. This encapsulates the instantiation logic within the factory class and promotes flexibility and maintainability in your code.
The Factory Method pattern is crucial for scenarios where the precise type of the object isn't known until runtime. By mastering this pattern, you'll have the ability to create code that is more modular and easier to extend in the future. For example, consider how you might need different document types in various contexts—using the Factory Method pattern ensures that your code can handle these variations efficiently and without unnecessary duplication.
This pattern offers several key advantages:
Are you ready to see this in action? Let's begin the practice section and implement the Factory Method pattern together!