Factory Pattern
- Defer the creation of an object to subclasses
- Relies on inheritance and polymorphism
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
Example Code