Abstract Factory – Provide the classes or interface classes for creating several classes and objects in the superclass. It allows the superclass to alter the object type or other that will be made.
From Design Pattern – Creational Patterns
Structure

Applicability
Using the abstract factory that the programs work with other related objects, the developers don’t want the source code to depend on the specific class. Maybe the developers know future extensibility or unknown preparatory that is why the developers use the abstract factory.
The abstract factory provides the interface classes or the abstract classes for creating objects from each subclass. Everyone class must have the responsibility only for a single thing. When the subclasses with multiple object types, maybe the programs must import the different factory methods into a stand-alone factory class.
Pros and Cons
Pros
- It can ensure the factory objects are compatible with each other.
- Avoid tight coupling between the client code and the factory code.
- Single Responsibility Principle.
- Open-closed principle.
Cons
- The source code will be more complicated than the original source code and isn’t easy to read because of importing multiple interface classes into a stand-alone class.
How to Implement
#1 Basic Sample
public interface IAbstractFactory<T> where T : class
{
IAbstractFactoryRepositoryA<T> CreateA(T entity);
IAbstractFactoryRepositoryB<T> CreateB(T entity);
}
class Repository<T> : IAbstractFactory<T> where T : class
{
public IAbstractFactoryRepositoryA<T> CreateA(T entity)
{
return new AbstractFactoryRepositoryA<T>();
}
public IAbstractFactoryRepositoryB<T> CreateB(T entity)
{
return new AbstractFactoryRepositoryB<T>();
}
}
public interface IAbstractFactoryRepositoryA<T> where T:class
{
bool Create(T entity);
}
public interface IAbstractFactoryRepositoryB<T> where T : class
{
bool Create(T entity);
}
class AbstractFactoryRepositoryA<T> : IAbstractFactoryRepositoryA<T> where T : class
{
public bool Create(T entity) => true;
}
class AbstractFactoryRepositoryB<T> : IAbstractFactoryRepositoryB<T> where T : class
{
public bool Create(T entity) => true;
}
#2 Web Application Project
Step1 Create two interface classes and the generic repository classes. One interface class file name sets “IAbstractFactoryA.” Another interface class file name sets “IAbstractFactoryB.” One generic repository class file name sets “AbstractFactoryA_Repository.” Another interface class file name sets “AbstractFactoryB_Repository.”

Step 2 Create CRUD in each repository and the “Get” function about the database connection to check the database connection status. The “Get” function helps the developer to double-check the dependency injection issue.
public class AbstractFactoryA_Repository<T> : IAbstractFactoryA<T> where T : class
{
private readonly DemoDbContext dbContext;
public AbstractFactoryA_Repository(DemoDbContext _dbContext)
{
this.dbContext = _dbContext;
}
public AbstractFactoryA_Repository()
{ }
public Task<bool> Get()
{
if (dbContext != null)
{
var o = dbContext.Set<T>().ToList();
return Task.FromResult(true);
}
else
return Task.FromResult(false);
}
public Task<IEnumerable<T>> GetAll()
{
try
{
var obj = dbContext.Set<T>().ToList() as IEnumerable<T>;
return Task.FromResult(obj);
}
catch (Exception e)
{
Debug.WriteLine("Commit Exception Type: {0}", e.GetType());
Debug.WriteLine("Message: {0}", e.Message);
return null;
}
}
public Task<T> GetByID(int? id)
{
try {
var obj = dbContext.Set<T>().Find(id.Value) as T;
return Task.FromResult(obj);
}
catch (Exception e)
{
Debug.WriteLine("Commit Exception Type: {0}", e.GetType());
Debug.WriteLine("Message: {0}", e.Message);
return null;
}
}
public Task Create(T entity)
{
try
{
dbContext.Set<T>().Add(entity);
dbContext.SaveChanges();
return Task.FromResult(true);
}
catch (Exception e)
{
Debug.WriteLine("Commit Exception Type: {0}", e.GetType());
Debug.WriteLine("Message: {0}", e.Message);
return Task.FromResult(false);
}
}
public Task Update(T entity)
{
try
{
dbContext.Entry(entity).State = EntityState.Modified;
dbContext.SaveChanges();
return Task.FromResult(true);
}
catch (Exception e)
{
Debug.WriteLine("Commit Exception Type: {0}", e.GetType());
Debug.WriteLine("Message: {0}", e.Message);
return Task.FromResult(false);
}
}
public Task Delete(T entity)
{
try
{
dbContext.Entry(entity).State = EntityState.Deleted;
dbContext.SaveChanges();
return Task.FromResult(true);
}
catch (Exception e)
{
Debug.WriteLine("Commit Exception Type: {0}", e.GetType());
Debug.WriteLine("Message: {0}", e.Message);
return Task.FromResult(false);
}
}
}
Step 3 Create an interface class that describes all of the interface-generic repositories. This interface class file name sets “IAbstractFactory.”

public interface IAbstractFactory<T> where T : class
{
IAbstractFactoryA<T> CreateA();
IAbstractFactoryB<T> CreateB();
}
Step 4 Create a generic repository for the “IAbstractFactory.” This repository class file name sets “AbstractFactoryRepo.”

Step 6 Statement two interface functions and do the dependency injection about IAbstractFactoryA and IAbstractFactoryB.

public class AbstractFactoryRepo<T> : IAbstractFactory<T> where T : class
{
private readonly IAbstractFactoryA<T> RepoA;
private readonly IAbstractFactoryB<T> RepoB;
public AbstractFactoryRepo(
IAbstractFactoryA<T> _RepoA,
IAbstractFactoryB<T> _RepoB)
{
this.RepoA = _RepoA;
this.RepoB = _RepoB;
}
public IAbstractFactoryA<T> CreateA()
{
if (RepoA == null)
return new AbstractFactoryA_Repository<T>();
else
return this.RepoA;
}
public IAbstractFactoryB<T> CreateB()
{
if (RepoA == null)
return new AbstractFactoryB_Repository<T>();
else
return RepoB;
}
}
Reference
2 Comments