logo

C# How to implement the abstract factory pattern to hide implementation of the concrete class

The abstract factory pattern delegates responsiblity of instantiation of the concrete class to another object. The abstract factory can have several different type of factories that it requests object generation with. In this example, I have built an BusinessView Factory for mapping my entity framework class data generated by code first into my business view classes.

From my unit of work repository pattern, I invoke the GetEmployeesBySupervisorId method which returns a list of EmployeeView objects. Within the GetEmployeesBySupervisorId method I use linq code to extract a query resultset of employees. Each employee is mapped to the employeeview business view class by use of the abstract factory using the business view class constructor. The Abstract factory has two abstract methods which with overrides in the concrete application class: MapSupervisorView and MapEmployeeView. The result is separation of concerns. The result is the implementation of the concrete class is hidden from the client.

The use of the abstract factory pattern will allow millions of developers to participate in building of my Millennium ERP without having to contend for resource. Contention is not of God, therefore, we must build abstract models that reduce programmer contention.

The xUnit Test


public void TestGetEmployeesBySupervisorId()
        {
            
            int supervisorId = 1;
            UnitOfWork unitOfWork = new UnitOfWork();
            List<EmployeeView>list = unitOfWork.supervisorRepository.GetEmployeesBySupervisorId(supervisorId);

            int count = 0;
            foreach (var item in list)
            {
                output.WriteLine($"{item.EmployeeId} {item.EmployeeName}");
                count++;
            }
            Assert.True(count>0);
            
        }

Abstract Factory Pattern


  public abstract class AbstractFactory
    {
        public abstract SupervisorView MapSupervisorView(Supervisor supervisor, Supervisor parentSupervisor);
        public abstract EmployeeView MapEmployeeView(Employee employee);
    }
    public abstract class BusinessViewFactory : AbstractFactory
    {
    }
    public class ApplicationViewFactory : BusinessViewFactory
    {
        public override SupervisorView MapSupervisorView(Supervisor supervisor, Supervisor parentSupervisor)
        {
            return new SupervisorView(supervisor, parentSupervisor);
        }
        public override EmployeeView MapEmployeeView(Employee employee)
        {
            return new EmployeeView(employee);
        }
    }

The Business Views


 public class SupervisorView 
    {
        
       public SupervisorView()
        {
           
        }
        public SupervisorView(Supervisor supervisor,Supervisor parentSupervisor)
        {
            this.SupervisorName = supervisor.AddressBook.Name;
            this.SupervisorAddressId = supervisor.AddressBook.AddressId;
            this.ParentSupervisorId = supervisor.ParentSupervisorId;
            if (this.ParentSupervisorId != null)
            {
                this.ParentSupervisorName = parentSupervisor.AddressBook.Name;
                this.ParentSupervisorCode = parentSupervisor.SupervisorCode;
                this.ParentSupervisorId = parentSupervisor.SupervisorId;
                this.ParentSupervisorTitle = parentSupervisor.UDC.Value;
                this.ParentSupervisorAddressId = parentSupervisor.AddressBook.AddressId;
            }

            this.SupervisorCode = supervisor.SupervisorCode;
            this.SupervisorId = supervisor.SupervisorId;
            this.Title = supervisor.UDC.Value;
        }

         public Supervisor parentsupervisor { get; set; }
        public long? SupervisorId { get; set; }
        public long? SupervisorAddressId { get; set; }
        public string SupervisorName { get; set; }
        public string Title { get; set; }
        public string SupervisorCode { get; set; }

        public long? ParentSupervisorId { get; set; }
        public long? ParentSupervisorAddressId { get; set; }
        public string ParentSupervisorName { get; set; }
        public string ParentSupervisorTitle { get; set; }
        public string ParentSupervisorCode { get; set; }


    }
    public class EmployeeView
    {
        public EmployeeView() { }
        public EmployeeView(Employee employee)
        {
            this.EmployeeId = employee.EmployeeId;
            this.EmployeeName = employee.AddressBook.Name;
            this.EmployeeTitle = employee.UDC.Value;
        }

        public long? EmployeeId { get; set; }
        public string EmployeeName { get; set; }
        public string EmployeeTitle { get; set; }
    }
 

The Unit of Work Repository Pattern


    public class SupervisorRepository : Repository<Supervisor>
    {
        private ApplicationViewFactory applicationViewFactory;
      
        Entities _dbContext;
        public SupervisorRepository(DbContext db) : base(db)
        {
            _dbContext = (Entities)db;
            applicationViewFactory = new ApplicationViewFactory();
        }
        public List<EmployeeView> GetEmployeesBySupervisorId(int supervisorId)
        {
            var resultList = (from supervisoremployee in _dbContext.SupervisorEmployees
                                                  join employee in _dbContext.Employees on
                                                  supervisoremployee.EmployeeId equals employee.EmployeeId
                                                  where supervisoremployee.SupervisorId == supervisorId
                                                 
                                                  select employee

                );
            List<EmployeeView> list = new List<EmployeeView>();
            foreach (var item in resultList)
            {
                list.Add(applicationViewFactory.MapEmployeeView(item));
            }

            return  list;

        }
        
    }
s