The Factory Method pattern is one of the creational design patterns in software engineering. It provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. This pattern promotes loose coupling between the client code and the concrete classes it creates.
In this tutorial, we'll explore the Factory Method pattern, understand its components, and see how it can be implemented in real-world scenarios.
The core idea behind the Factory Method pattern is to delegate the responsibility of object creation to subclasses. This allows for more flexibility and scalability in your codebase. The pattern involves:
By using this pattern, you can create objects without specifying the exact class of object that will be created. This is particularly useful when you want to decouple the client code from the concrete classes it uses.
Let's dive into a practical example to illustrate how the Factory Method pattern works.
Suppose we have an application that needs to create different types of documents (e.g., PDF, Word). We can use the Factory Method pattern to encapsulate the document creation logic.
First, let's define a Document interface with a common method for displaying the document type.
1interface Document {2display(): void;3}
Next, we'll create concrete classes that implement the Document interface.
1class PDFDocument implements Document {2display() {3console.log("Displaying a PDF document.");4}5}67class WordDocument implements Document {8display() {9console.log("Displaying a Word document.");10}11}
Now, let's define a Creator interface with a factory method.
1interface Creator {2createDocument(): Document;3}
Finally, we'll implement concrete classes that provide specific implementations of the factory method.
1class PDFCreator implements Creator {2createDocument(): Document {3return new PDFDocument();4}5}67class WordCreator implements Creator {8createDocument(): Document {9return new WordDocument();10}11}
We can now use these creators to create and display documents without specifying the exact class of document.
1function clientCode(creator: Creator) {2const document = creator.createDocument();3document.display();4}56const pdfCreator = new PDFCreator();7clientCode(pdfCreator); // Output: Displaying a PDF document.89const wordCreator = new WordCreator();10clientCode(wordCreator); // Output: Displaying a Word document.
Let's extend our example by adding another type of document, say TextDocument.
First, we'll create a new concrete class for the text document.
1class TextDocument implements Document {2display() {3console.log("Displaying a Text document.");4}5}
Next, we'll create a new creator for the text document.
1class TextCreator implements Creator {2createDocument(): Document {3return new TextDocument();4}5}
We can now use the new creator to create and display a text document.
1const textCreator = new TextCreator();2clientCode(textCreator); // Output: Displaying a Text document.
In this tutorial, we explored the Factory Method pattern, which allows you to create objects without specifying the exact class of object that will be created. This promotes loose coupling and makes your codebase more flexible.
Next, you can learn about the Abstract Factory Pattern, which extends the Factory Method pattern by providing a way to create families of related or dependent objects without specifying their concrete classes. This pattern is particularly useful when dealing with complex systems with multiple interdependent object types.
Stay tuned for more design patterns and best practices in software engineering!