Factory Method – Provides interface classes for creating objects in the superclass. It allows the superclass changes the object types that will be made.
From Design Pattern – Creational Patterns
Structure
Applicability
Pros and Cons
PROS
CONS
How to Implement
#1 Basic Sample
class Client
{
private IFactoryMethod<string> repo;
public Client(IFactoryMethod<string> _repo)
{
this.repo = _repo;
}
public void Main()
{
var o = new ConcreteCreatorA<string>(repo);
Console.WriteLine(o.SomeOperation());
}
}
public abstract class Creator<T> where T : class
{
public abstract IFactoryMethod<T> FactoryMethod();
public string SomeOperation()
{
var product = FactoryMethod();
var result = "Creator: The same creator's code has just worked with "
+ product.Operation();
return result;
}
}
class ConcreteCreatorA<T> : Creator<T> where T : class
{
private IFactoryMethod<T> repo;
public ConcreteCreatorA(IFactoryMethod<T> _repo)
{
this.repo = _repo;
}
public override IFactoryMethod<T> FactoryMethod()
{
if (repo == null)
return new FactoryMethodA<T>();
else
return this.repo;
}
}
public interface IFactoryMethod<T> where T : class
{
string Operation();
}
public class FactoryMethodA<T> : IFactoryMethod<T> where T : class
{
private string str;
public FactoryMethodA(string _str)
{
this.str = _str;
}
public FactoryMethodA()
{ }
public string Operation()
{
return "{Result of ConcreteProductA}";
}
}
#2 Web Application Project
Step 1 Create the generic interface class files and two generic repository files about the FactoryMethod. A new generic interface class file name sets “IFactoryMethod” under the Core project. One new generic repository class file name sets “FactoryMethodRepoA.” Another new generic repository class file name sets “FactoryMethodRepoB.” The developers put these generic class files under the Infra project.
Step 2 Add a function in the IFactoryMethod.
public interface IFactoryMethod<T> where T : class
{
Task<T> GetById(int? id);
} Step 3 FactoryMethodRepoA and FactoryMethodRepoB inherits the IFactoryMethod interface class file, declare the IGenericTypeRepository interface class by the dependency injection methods. The IFactoryMethod<T>.GetById calls IGenericTypeRepository<T>.GetById function.
public class FactoryMethodRepoA<T> : IFactoryMethod<T> where T : class
{
private readonly IGenericTypeRepository<T> repo;
public FactoryMethodRepoA(IGenericTypeRepository<T> _repo)
{
this.repo = _repo;
}
public FactoryMethodRepoA()
{ }
public Task<T> GetById(int? id)
{
return id.Value != 0 ? Task.Run(async () => await repo.GetById(id.Value) as T) : null;
}
} Note: The FactoryMethodRepoB class file source code is the same as the FactoryMethodRepoA class file source code.
Step 4 Create the new class file which name sets “Creator” under the Core project. The Creator class file declares the IFactoryMethod interface class files, creates a new function in which the name sets “GetByID_Creator.”
public abstract class Creator<T> where T : class
{
public abstract IFactoryMethod<T> Repo();
public Task<T> GetByID_Creator(int id)
{
var obj = Repo();
return Task.Run(() => obj.GetById(id).Result as T);
}
} Step 5 Create two concrete class files under the Infra project. One class file name sets “ConcreteA.” Another class file name sets “ConcreteB.” Everyone concrete class file inherits the Creator class file, then creates a way in which the name sets “From_Info,” which descript the concrete information return string variable.
public class ConcreteA<T> : Creator<T> where T : class
{
private readonly IFactoryMethod<T> repo;
public ConcreteA(IFactoryMethod<T> _repo)
{
this.repo = _repo;
}
public override IFactoryMethod<T> Repo()
{
if (repo == null)
return new FactoryMethodRepoA<T>();
else
return this.repo;
}
public string From_Info() => "From ConcreteB class.";
} Note: The ConcretB class file source code is the same as the ConcreteA class file source code.
Step 6 Create a new controller file which name sets “FactoryMethodController” under the web project. Create the index view file under the web project’s Views folder.
public class FactoryMethodController : Controller
{
private ConcreteA<Enterprise_MVC_Core> concreteA;
private ConcreteB<Enterprise_MVC_Core> concreteB;
public FactoryMethodController(IFactoryMethod<Enterprise_MVC_Core> _repo)
{
this.concreteA = new ConcreteA<Enterprise_MVC_Core>(_repo);
this.concreteB = new ConcreteB<Enterprise_MVC_Core>(_repo);
}
public IActionResult Index()
{
var objA = concreteA.GetByID_Creator(1).Result;
var objA_From = concreteA.From_Info();
var objB = concreteB.GetByID_Creator(2).Result;
var objB_From = concreteB.From_Info();
ViewData["P_1"] = objA_From.ToString().Trim();
ViewData["P_2"] = objB_From.ToString().Trim();
Tuple<IEnumerable<Enterprise_MVC_Core>, IEnumerable<Enterprise_MVC_Core>> tuple_View
= new Tuple<IEnumerable<Enterprise_MVC_Core>, IEnumerable<Enterprise_MVC_Core>>(
new List<Enterprise_MVC_Core> { objA },
new List<Enterprise_MVC_Core> { objB }
);
return View(tuple_View);
}
}
Reference
What is the API gateway? An API gateway is an API management tool that sits…
The .NET 5 SDK is a kind of milestone in the .NET world. The .NET…
In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupling software…
In the field of software engineering, the interface segregation principle (ISP) states that no code…
Subtype Requirement: Let be a property provable about objects of type T. Then should be true for objects of type S where S is…
In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be…
View Comments