The Factory Design Pattern in C# is a creational design pattern that provides an interface for creating objects, but it allows subclasses to alter the type of objects that will be created. It is often used when you have a superclass with multiple subclasses, and you want to create an object of one of those subclasses based on certain conditions. There are different types of factory patterns, including the Simple Factory, Factory Method, and Abstract Factory.
Here’s an example of the Factory Design Pattern in C# and a brief overview of each type:
Simple Factory
The Simple Factory is not an official design pattern, but it’s a simplified version of the factory pattern. It provides a single class with a method for creating objects.
public class SimpleFactory
{
public static IShape GetShape(string shapeType)
{
switch (shapeType.ToLower())
{
case "circle":
return new Circle();
case "rectangle":
return new Rectangle();
case "triangle":
return new Triangle();
default:
throw new ArgumentException("Invalid shape type");
}
}
}
Factory Method
The Factory Method pattern defines an interface for creating an object but allows subclasses to alter the type of objects that will be created. Each concrete subclass provides its own implementation of the factory method.
public abstract class ShapeFactory
{
public abstract IShape CreateShape();
}
public class CircleFactory : ShapeFactory
{
public override IShape CreateShape()
{
return new Circle();
}
}
public class RectangleFactory : ShapeFactory
{
public override IShape CreateShape()
{
return new Rectangle();
}
}
// Usage:
ShapeFactory factory = new CircleFactory();
IShape circle = factory.CreateShape();
Abstract Factory
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s used when you need to ensure that the created objects are compatible with each other.
public interface IShapeFactory
{
IShape CreateShape();
IBorder CreateBorder();
}
public class CircleFactory : IShapeFactory
{
public IShape CreateShape()
{
return new Circle();
}
public IBorder CreateBorder()
{
return new CircleBorder();
}
}
public class RectangleFactory : IShapeFactory
{
public IShape CreateShape()
{
return new Rectangle();
}
public IBorder CreateBorder()
{
return new RectangleBorder();
}
}
// Usage:
IShapeFactory factory = new CircleFactory();
IShape circle = factory.CreateShape();
IBorder border = factory.CreateBorder();
Use Case
In all these factory patterns, the primary use case is to abstract the object creation process, making it more flexible and maintainable. You can change the concrete implementations of the created objects without affecting the client code. These patterns are useful when you have a family of related objects and you want to decouple their instantiation from the client code, promoting loose coupling and adherence to the Open-Closed Principle.