What is the Factory Method Design Pattern?
The factory method design pattern is a creational design pattern that defines an interface for creating objects in a super class, but allows subclasses to alter the type of objects that will be created.
The factory method design pattern is used to define a method that creates objects, but lets subclasses decide which class to instantiate. The factory method design pattern lets a class defer instantiation to subclasses.
The factory method design pattern is also known as the virtual constructor pattern.
For example, let’s say we have a class called Shape
, and we want to make a program that can create different shapes like circles, squares, and triangles. We could make the Shape
class have a method called createShape
that creates a shape, but we can't know what kind of shape to create yet. That's where the factory method design pattern comes in.
We can make a subclass of Shape
for each kind of shape we want to be able to create (like Circle
, Square
, and Triangle
). Each of these subclasses can have its own version of the createShape
method that knows how to create the right kind of shape.
Here’s an example of the factory method design pattern using:
abstract class Shape
{
public abstract void Draw();
}
class Circle : Shape
{
public override void Draw()
{
// Code to draw a circle.
}
}
class Square : Shape
{
public override void Draw()
{
// Code to draw a square.
}
}
class Triangle : Shape
{
public override void Draw()
{
// Code to draw a triangle.
}
}
abstract class ShapeCreator
{
public abstract Shape FactoryMethod();
public void AnOperation()
{
// Call the factory method to create a Shape object.
Shape shape = FactoryMethod();
// Now, use the shape.
shape.Draw();
}
}
class CircleCreator : ShapeCreator
{
public override Shape FactoryMethod()
{
return new Circle();
}
}
class SquareCreator : ShapeCreator
{
public override Shape FactoryMethod()
{
return new Square();
}
}
class TriangleCreator : ShapeCreator
{
public override Shape FactoryMethod()
{
return new Triangle();
}
}
In this example, the Shape
class is abstract and defines the Draw
method. The Circle
, Square
, and Triangle
classes are subclasses of Shape
that override the Draw
method to draw a circle, square, and triangle, respectively.
The ShapeCreator
class is abstract and defines the FactoryMethod
interface, which is used to create Shape
objects. The CircleCreator
, SquareCreator
, and TriangleCreator
classes are subclasses of ShapeCreator
that override the FactoryMethod
to create Circle
, Square
, and Triangle
objects, respectively.
The AnOperation
method in the ShapeCreator
class uses the FactoryMethod
to create a Shape
object, which it then uses by calling the Draw
method on it. When AnOperation
is called on an instance of CircleCreator
, SquareCreator
, or TriangleCreator
, it will create and draw a circle, square, or triangle, respectively.
To use the factory method design pattern in your client code, you will need to instantiate the appropriate Creator
or ShapeCreator
subclass and then call the desired method on it.
Creator creator = new ConcreteCreator1();
creator.AnOperation();
ShapeCreator shapeCreator = new CircleCreator();
shapeCreator.AnOperation();
This will create and use a ConcreteProduct1
object or a Circle
object, respectively, depending on which Creator
or ShapeCreator
subclass is instantiated.
You can also use a factory method to create objects in a more dynamic way, by passing in parameters to the factory method to specify which type of object to create. For example:
abstract class Creator
{
public abstract Product FactoryMethod(string type);
}
class ConcreteCreator : Creator
{
public override Product FactoryMethod(string type)
{
if (type == "product1")
return new ConcreteProduct1();
else if (type == "product2")
return new ConcreteProduct2();
else
return null;
}
}
// In client code:
Creator creator = new ConcreteCreator();
Product product = creator.FactoryMethod("product1");
This allows you to create different types of Product
objects based on the value of the type
parameter passed to the FactoryMethod
.
Imagine that you are building a web application that needs to retrieve data from different types of data sources, such as a database, a file, or a web service. You could use the factory method design pattern to create a data access layer that is able to create the appropriate data access object for the current data source.
Here is an example of how this could be implemented in C#:
abstract class DataAccessObject
{
public abstract void Select();
public abstract void Insert();
public abstract void Update();
public abstract void Delete();
}
class SqlDataAccessObject : DataAccessObject
{
public override void Select()
{
Console.WriteLine("Selecting from SQL database.");
}
public override void Insert()
{
Console.WriteLine("Inserting into SQL database.");
}
public override void Update()
{
Console.WriteLine("Updating SQL database.");
}
public override void Delete()
{
Console.WriteLine("Deleting from SQL database.");
}
}
class FileDataAccessObject : DataAccessObject
{
public override void Select()
{
Console.WriteLine("Selecting from file.");
}
public override void Insert()
{
Console.WriteLine("Inserting into file.");
}
public override void Update()
{
Console.WriteLine("Updating file.");
}
public override void Delete()
{
Console.WriteLine("Deleting from file.");
}
}
class WebServiceDataAccessObject : DataAccessObject
{
public override void Select()
{
Console.WriteLine("Selecting from web service.");
}
public override void Insert()
{
Console.WriteLine("Inserting into web service.");
}
public override void Update()
{
Console.WriteLine("Updating web service.");
}
public override void Delete()
{
Console.WriteLine("Deleting from web service.");
}
}
And here is the where factory comes in:
// Concrete creator.
class DataAccessFactory
{
static DataAccessFactory instance = null;
DataAccessObject dao = null;
// Constructor is private to prevent direct instantiation.
private DataAccess()
{
// Read configuration setting to determine which factory to use.
string dataSource = ConfigurationManager.AppSettings["DataSource"];
if (dataSource == "SQL")
dao = new SqlDataAccessObject();
else if (dataSource == "File")
dao = new FileDataAccessObject();
else if (dataSource == "WebService")
dao = new WebServiceDataAccessObject();
else
throw new Exception("There is no accessible object for configuration. Please check out DataSource");
}
public static DataAccess GetInstance()
{
if (instance == null)
instance = new DataAccess();
return instance;
}
public void Select()
{
dao.Select();
}
public void Insert()
{
dao.Insert();
}
public void Update()
{
dao.Update();
}
public void Delete()
{
dao.Delete();
}
}
And you can use it on client like this:
DataAccess.GetInstance().Select();
DataAccess.GetInstance().Insert();
DataAccess.GetInstance().Update();
DataAccess.GetInstance().Delete();
You can make it without GetInstance method like this below:
// Concrete creator.
class DataAccessFactory
{
public static DataAccessObject CreateInstance()
{
DataAccessObject dao = null;
// Read configuration setting to determine which factory to use.
string dataSource = ConfigurationManager.AppSettings["DataSource"];
if (dataSource == "SQL")
dao = new SqlDataAccessObject();
else if (dataSource == "File")
dao = new FileDataAccessObject();
else if (dataSource == "WebService")
dao = new WebServiceDataAccessObject();
else
throw new Exception("There is no accessible object for configuration. Please check out DataSource");
return dao;
}
}
And of course you can make it more dynamic with using reflection to create the DataAccessObject at runtime:
// Concrete creator.
class DataAccessFactory
{
public static DataAccessObject CreateInstance()
{
DataAccessObject dao = null;
// Read configuration setting to determine which factory to use.
string dataAccessType = ConfigurationManager.AppSettings["DataAccessType"];
Type t = Type.GetType(dataAccessType);
dao = (DataAccessObject)Activator.CreateInstance(t);
if(dao is null)
throw new Exception("There is no accessible object for configuration. Please check out DataAccessType");
return dao;
}
}
On client side you can just use it like this:
var dataAccessObject = DataAccessFactory.CreateInstance();
dataAccessObject.Select();
dataAccessObject.Insert();
dataAccessObject.Update();
dataAccessObject.Delete();
Conclusion
The factory method design pattern is a creational design pattern that defines an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. This allows for the creation of objects to be delegated to subclasses, which gives them the flexibility to alter the type of objects that will be created, and makes it easy to add new types of objects to the system.
The factory method design pattern consists of an interface for creating objects, a concrete creator class that implements the factory method to create a concrete object, and one or more concrete product classes that represent the objects that the factory method creates. The client code creates objects by calling the factory method on the creator object, which then creates and returns a new object of the desired type.
The factory method design pattern can be implemented using an abstract creator class that contains the factory method and is subclassed by the concrete creator, or it can be implemented using a concrete creator class that uses the factory method to create the desired object. It can also be implemented using reflection to create the object at runtime.
Thanks for reading! If you found the article helpful, you can clap and follow. So you will notified of new articles.
# Reference
It was created with the help of ChatGPT AI.