Design Patterns

Last Updated: 9/5/2024

Factory Pattern

  • Defer the creation of an object to subclasses
  • Relies on inheritance and polymorphism

Classical Structure

Factory Classical Structure

Scenario

  • Build a new web app framework and use it to build web app

Problem

  • Controller is tightly coupled with ViewEngine. To allow clients to use their own ViewEngine. Define an interface and pass it to the Render method.
  • In every controller you have to pass the ViewEngine
public interface IViewEngine
{
    string Render(string viewName, Dictionary<string, object> context);
}
public class MatchaViewEngine: IViewEngine
{
    public string Render(string viewName, Dictionary<string, object> context)
    {
        return "View Rendered by Matcha";
    }
}
public class Controller
{
    public void Render(string viewName, Dictionary<string, object> context, IViewEngine viewEngine)
    {
        var html = viewEngine.Render(viewName, context);
        Console.WriteLine(html);
    }
}
public class ProductsController: Controller
{
    public void ListProducts()
    {
        Dictionary<string, object> context = new Dictionary<string, object>();
        Render("products.html", context, new MatchaViewEngine());
    }
}

Solution

  • Base controller supplies the default ViewEngine. Derived classes can override and return different ViewEngine
public interface IViewEngine
{
    string Render(string viewName, Dictionary<string, object> context);
}
public class MatchaViewEngine: IViewEngine
{
    public string Render(string viewName, Dictionary<string, object> context)
    {
        return "View Rendered by Matcha";
    }
}
public class SharpViewEngine: IViewEngine
{
    public string Render(string viewName, Dictionary<string, object> context)
    {
        return "View Rendered by Sharp";
    }
}
public class Controller
{
    public void Render(string viewName, Dictionary<string, object> context)
    {
        var viewEngine = CreateViewEngine();
        var html = viewEngine.Render(viewName, context);
        Console.WriteLine(html);
    }

    protected virtual IViewEngine CreateViewEngine()
    {
        return new MatchaViewEngine();
    }
}
public class SharpController: Controller
{
    protected override IViewEngine CreateViewEngine()
    {
        return new SharpViewEngine();
    }
}
public class ProductsController: SharpController
{
    public void ListProducts()
    {
        Dictionary<string, object> context = new Dictionary<string, object>();
        Render("products.html", context);
    }
}

Example Structure

Factory Example Structure

Example Code