Factory Method Pattern | Creational Design Pattern
Factory Method Pattern
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. It promotes the idea of "deferring the instantiation to subclasses." This pattern is particularly useful when a class cannot anticipate the class of objects it needs to create.
Key components and concepts involved in the Factory Method Pattern:
1. Product:
- Declares the interface for the objects that the factory method will create.
2. Concrete Product:
- Implements the `Product` interface.
3. Creator:
- Declares the factory method, which returns an object of type `Product`. It may also contain other methods that operate on `Product` objects.
4. Concrete Creator:
- Overrides the factory method to return an instance of a specific `Concrete Product`.
Example in C#:
// Product
interface IProduct
{
void Display();
}
// Concrete Product A
class ConcreteProductA : IProduct
{
public void Display()
{
Console.WriteLine("Concrete Product A");
}
}
// Concrete Product B
class ConcreteProductB : IProduct
{
public void Display()
{
Console.WriteLine("Concrete Product B");
}
}
// Creator
interface ICreator
{
IProduct FactoryMethod();
}
// Concrete Creator A
class ConcreteCreatorA : ICreator
{
public IProduct FactoryMethod()
{
return new ConcreteProductA();
}
}
// Concrete Creator B
class ConcreteCreatorB : ICreator
{
public IProduct FactoryMethod()
{
return new ConcreteProductB();
}
}
// Client
class Client
{
public void DisplayProduct(ICreator creator)
{
IProduct product = creator.FactoryMethod();
product.Display();
}
}
// Usage
class Program
{
static void Main()
{
Client client = new Client();
// Client uses Creator A
ICreator creatorA = new ConcreteCreatorA();
client.DisplayProduct(creatorA);
// Client uses Creator B
ICreator creatorB = new ConcreteCreatorB();
client.DisplayProduct(creatorB);
}
}
In this example:
- The `IProduct` interface declares the `Display` method that concrete products will implement.
- Concrete products (`ConcreteProductA` and `ConcreteProductB`) implement the `IProduct` interface.
- The `ICreator` interface declares the `FactoryMethod`, which is responsible for creating an instance of `IProduct`.
- Concrete creators (`ConcreteCreatorA` and `ConcreteCreatorB`) implement the `ICreator` interface and provide their own implementation of the `FactoryMethod`.
- The `Client` class uses the factory method to create and display products without knowing the specific concrete product classes.
The key benefit of the Factory Method Pattern is that it allows the client to work with abstract product interfaces and creators, promoting flexibility and extensibility. Subclasses can override the factory method to produce different product variations, and clients can use the same interface to work with various product implementations.
A real-world example of the Factory Method Pattern can be found in the development of document processing applications where different document types need to be created. Let's consider a scenario of a document editor that supports various document formats such as PDF and Word.
Real-world Example: Document Editor
1. Product: `Document`
- Declares the interface for documents.
2. Concrete Products: `PDFDocument`, `WordDocument`
- Implement the `Document` interface for specific document types.
3. Creator: `DocumentCreator`
- Declares the factory method for creating documents.
4. Concrete Creators: `PDFDocumentCreator`, `WordDocumentCreator`
- Implement the `DocumentCreator` interface and provide their own implementation of the factory method.
Example in C#:
// Product
interface Document
{
void Open();
void Save();
}
// Concrete Product: PDFDocument
class PDFDocument : Document
{
public void Open()
{
Console.WriteLine("Opening PDF document");
}
public void Save()
{
Console.WriteLine("Saving PDF document");
}
}
// Concrete Product: WordDocument
class WordDocument : Document
{
public void Open()
{
Console.WriteLine("Opening Word document");
}
public void Save()
{
Console.WriteLine("Saving Word document");
}
}
// Creator
interface DocumentCreator
{
Document CreateDocument();
}
// Concrete Creator: PDFDocumentCreator
class PDFDocumentCreator : DocumentCreator
{
public Document CreateDocument()
{
return new PDFDocument();
}
}
// Concrete Creator: WordDocumentCreator
class WordDocumentCreator : DocumentCreator
{
public Document CreateDocument()
{
return new WordDocument();
}
}
// Client
class DocumentEditor
{
public void EditDocument(DocumentCreator documentCreator)
{
Document document = documentCreator.CreateDocument();
document.Open();
document.Save();
}
}
// Usage
class Program
{
static void Main()
{
DocumentEditor documentEditor = new DocumentEditor();
// Editing a PDF document
DocumentCreator pdfDocumentCreator = new PDFDocumentCreator();
documentEditor.EditDocument(pdfDocumentCreator);
// Editing a Word document
DocumentCreator wordDocumentCreator = new WordDocumentCreator();
documentEditor.EditDocument(wordDocumentCreator);
}
}
In this example, the `DocumentCreator` interface declares the factory method `CreateDocument`, and concrete creators (`PDFDocumentCreator` and `WordDocumentCreator`) provide their own implementations. The client (`DocumentEditor`) uses the factory method to create and edit documents without knowing the specific document classes.
This pattern allows for the extensibility of the document editor to support additional document formats in the future. Each document format is encapsulated within its concrete creator, and the client can easily switch between document types without modifying the client code.
Comments
Post a Comment