The Simple Factory pattern provides a way of creating objects without describing the exact class of objects that will be created.
It is also known as a Static Factory Method pattern.
Getting Started
The Simple Factory pattern defines a static method that is responsible for creating objects, and this method is typically called a “factory method”.
The factory method takes one or more parameters that are used to determine which type of object to create, and it returns an instance of the appropriate class.
What Problems does Simple Factory Pattern Solve
- The Simple Factory pattern solves the problem of creating objects in a way that is decoupled from the client code using a factory method.
- The factory method takes care of the responsibility of determining which class to instantiate and creating an instance of that class.
- This allows for flexibility in the system, as new classes can be added and used by the factory method without affecting the client code.
Code & Explanation
class DocumentFactory
{
public static IDocument CreateDocument(string documentType)
{
if (documentType == "PDF")
return new PdfDocument();
else if (documentType == "Word")
return new WordDocument();
else
throw new ArgumentException("Invalid document type.");
}
}
interface IDocument
{
void Open();
void Save();
}
class PdfDocument : IDocument
{
public void Open()
{
Console.WriteLine("PDF Document Open");
}
public void Save()
{
Console.WriteLine("PDF Document Save");
}
}
class WordDocument : IDocument
{
public void Open()
{
Console.WriteLine("Word Document Open");
}
public void Save()
{
Console.WriteLine("Word Document Save");
}
}
In this example, the DocumentFactory
class defines a static method called CreateDocument
that takes a string parameter indicating the type of document to create.
This method checks the value of the documentType
parameter and returns an object of the appropriate class.
The IDocument
interface defines the behavior that all document classes should implement, PdfDocument
and WordDocument
classes are concrete implementations of this interface.
Client Code
private static void Main(string[] args)
{
IDocument document = DocumentFactory.CreateDocument("PDF");
document.Save();
document.Open();
Console.ReadLine();
}
The client code can use the DocumentFactory
class to create objects, but the type of objects that will be created is determined by the value of the documentType
parameter that is passed to the factory method.
Output
PDF Document Save
PDF Document Open
This pattern is a prime example of run time polymorphism
– we have a base IDocument
and in the run time, we create objects of either PDFDocument
or WordDocument
class.
Refactoring
We can replace the if/else blocks in the DocumentFactory
by using a Dictionary, let’s see it in action:
public static class DocumentFactory
{
private static Dictionary<string, IDocument> container = new Dictionary<string, IDocument>();
static DocumentFactory()
{
container.Add("PDF", new PdfDocument());
container.Add("Word", new WordDocument());
}
public static IDocument CreateDocument(string documentType)
{
return container[documentType].Clone();
}
}
We have created a Dictionary<string, IDocument> with a string
key and IDocument
value, and in the static constructor, we are adding the concrete types, along with the document type.
In the CreateDocument() method, we just return the dictionary value (IDocument
instance) as per the key (documentType
).
We have created a Clone() method to eliminate the return of the same IDocument
instance in the case of different calls.
Clone() method
We have defined Clone() in the IDocument
interface, and have implemented them in the concrete classes. Let’s have a look:
public interface IDocument
{
void Save();
void Open();
IDocument Clone();
}
public class PdfDocument : IDocument
{
public void Open()
{
Console.WriteLine("PDF Document Open");
}
public void Save()
{
Console.WriteLine("PDF Document Save");
}
public IDocument Clone()
{
return (IDocument)MemberwiseClone();
}
}
Let’s run the app and see the output:
PDF Document Save
PDF Document Open
GitHub
The full solution is available at – https://github.com/anurag1302/design-patterns
Design Pattern Series
Separate articles on Design patterns are available:
Conclusion
In this article, we have learned about the Simple Factory pattern, and how it helps to decouple the object creation process from the client code.