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:
- What the Factory Method pattern is and why it is used.
- How to implement the Factory Method pattern using a factory class.
- Creating different types of document classes (
WordDocument
andExcelDocument
) 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:
- This enum defines the supported types of documents (
WORD
andEXCEL
). You can easily extend this enum to include additional document types in the future, making the system flexible and scalable.
- This enum defines the supported types of documents (
-
The getDocument Method:
- This is the factory method that takes a
DocumentType
as a parameter and returns an instance of the corresponding document class. - The
switch
statement checks the provided document type and creates an instance ofWordDocument
orExcelDocument
accordingly. - If an unsupported or unknown document type is passed, the method throws an
IllegalArgumentException
. This guards against invalid input, ensuring robustness in your code.
- This is the factory method that takes a
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:
- We call the
getDocument
method ofDocumentFactory
withDocumentType.WORD
to instantiate aWordDocument
. - We then call the
open
method on theWordDocument
instance to demonstrate its functionality.
Similarly:
- We call the
getDocument
method ofDocumentFactory
withDocumentType.EXCEL
to instantiate anExcelDocument
. - We then call the
open
method on theExcelDocument
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:
- It encapsulates the object creation process, making the code more maintainable.
- It decouples client code from specific classes it needs to instantiate, enhancing flexibility.
- By adhering to the Single Responsibility Principle, it ensures factory classes focus solely on creating objects, promoting cleaner design.
- It enhances reusability, allowing for the introduction of new object types without modifying existing code.
- It allows for runtime decisions on class instantiation, enhancing adaptability.
Are you ready to see this in action? Let's begin the practice section and implement the Factory Method pattern together!