- Delegate, you do it on my behalf
- Create related or dependent objects without specifying there concrete classes
- Is a super factory that creates other factories
- Adds a layer of abstraction to the factory method pattern
Handout computers to Contract and Permanent employees based on the designation and employee type with below specifications:
Permanent employee
- Managerial position is eligible for mac book laptop
- Non managerial position is eligible for iMac desktop
- Managerial position is eligible for dell laptop
- Non managerial position is eligible for dell desktop
Sample Code Download: PatternsAbstractMethod.zip (Visual Studio 2017 Console App)
Basic Setup
Enums
public enum ComputerBrand
{
Apple,
Dell
}
{
Apple,
Dell
}
public enum ComputerProcessor
{
I3,
I5,
I7
}
public enum ComputerType
{
Laptop,
Desktop
}
public enum EmployeeDesignation
{
Manager,
NonManager
}
public enum EmployeeType
{
Contract = 1,
Permanent = 2
}
{
I3,
I5,
I7
}
public enum ComputerType
{
Laptop,
Desktop
}
public enum EmployeeDesignation
{
Manager,
NonManager
}
public enum EmployeeType
{
Contract = 1,
Permanent = 2
}
Model to Represent DB
public class EmpData
{
public string Name { get; set; }
public EmployeeDesignation Designation { get; set; }
public string Department { get; set; }
public EmployeeType EmployeeType { get; set; }
public string ComputerDetails { get; set; }
}
Filling and Displaying the Data
class Program
{
static void Main(string[] args)
{
var employees = FillEmployees();
PrintEmployees(employees);
Console.ReadLine();
}
private static List
{
var employees = new List
{
new EmpData
{
Name = "Jason",
Department = "IT",
Designation = EmployeeDesignation.Manager,
EmployeeType = EmployeeType.Contract
},
new EmpData
{
Name = "Jay",
Department = "IT",
Designation = EmployeeDesignation.NonManager,
EmployeeType = EmployeeType.Contract
},
new EmpData
{
Name = "Brian",
Department = "IT",
Designation = EmployeeDesignation.Manager,
EmployeeType = EmployeeType.Permanent
},
new EmpData
{
Name = "Susan",
Department = "IT",
Designation = EmployeeDesignation.NonManager,
EmployeeType = EmployeeType.Permanent
}
};
return employees;
}
private static string Tab()
{
return "\t";
}
private static void PrintEmployees(List
{
//header
Console.ForegroundColor = ConsoleColor.DarkYellow;
var header = $"#{Tab()}Name{Tab()}Department{Tab()}Type{Tab()}{Tab()}Designation{Tab()}ComputerDetails";
Console.WriteLine(header);
Console.ResetColor();
//no data
if (employees == null || !employees.Any())
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("No Data");
Console.ResetColor();
return;
}
//print data
var row = 1;
foreach (var emp in employees)
{
var message = row + Tab() + emp.Name + Tab() + emp.Department + Tab()+Tab() + emp.EmployeeType+Tab()+emp.Designation + Tab();
message += !string.IsNullOrWhiteSpace(emp.ComputerDetails)
? emp.ComputerDetails + Tab()
: "" + Tab();
Console.WriteLine(message);
row += 1;
}
}
}
Implementation
|
|
Adding Abstract Product Interfaces
Under folder AbstractProuct, create following interfaces
public interface ISystemBrand
{
//computer brand
string GetBrand();
}
public interface ISystemProcessor
{
string GetProcessor();
}
public interface ISystemType
{
string GetSystemType();
}
Adding Concrete Product Classes
Here we'll add the product classes which will implement the AbstractProduct Interfaces. Under folder ConcreteProduct add the following classes by implementing appropriate interfaces.
public class SystemMac : ISystemBrand
{
public string GetBrand()
{
return ComputerBrand.Apple.ToString();
}
}
public class SystemDell : ISystemBrand
{
public string GetBrand()
{
return ComputerBrand.Dell.ToString();
}
}
public class SystemTypeDesktop : ISystemType
{
public string GetSystemType()
{
return ComputerType.Desktop.ToString();
}
}
public class SystemTypeLaptop : ISystemType
{
public string GetSystemType()
{
return ComputerType.Laptop.ToString();
}
}
public class ProcessorI3 : ISystemProcessor
{
public string GetProcessor()
{
return ComputerProcessor.I3.ToString();
}
}
public class ProcessorI5 : ISystemProcessor
{
public string GetProcessor()
{
return ComputerProcessor.I5.ToString();
}
}
public class ProcessorI7 : ISystemProcessor
{
public string GetProcessor()
{
return ComputerProcessor.I7.ToString();
}
}
Adding Abstract Interface
Under folder AbstractInterface add a factory interface.
public interface IComputerFactory
{
ISystemBrand SystemBrand();
ISystemProcessor SystemProcessor();
ISystemType SystemType();
}
Adding Concrete Factory Classes
Under folder ConcreateFactory create the factory classes by implmenting IComputeFactory interface. These are the classes which will return the appropriate ConcreteProduct objects.
public class ComputerDellFactory : IComputerFactory
{
public ISystemBrand SystemBrand()
{
return new SystemDell();
}
public ISystemProcessor SystemProcessor()
{
return new ProcessorI5();
}
//make this virtual since ComputerDellLaptopFactory will inherit from ComputerDellFactory
public virtual ISystemType SystemType()
{
return new SystemTypeDesktop();
}
}
public class ComputerDellLaptopFactory : ComputerDellFactory
{
public override ISystemType SystemType()
{
return new SystemTypeLaptop();
}
}
public class ComputerMacFactory : IComputerFactory
{
public ISystemBrand SystemBrand()
{
return new SystemMac();
}
public ISystemProcessor SystemProcessor()
{
return new ProcessorI7();
}
//making this virtual since ComputerMacbookFactory will inherit from This factory and we'll overwrite the SystemType there
public virtual ISystemType SystemType()
{
return new SystemTypeDesktop();
}
}
public class ComputerMacBookFactory : ComputerMacFactory
{
public override ISystemType SystemType()
{
return new SystemTypeLaptop();
}
}
and finally implement the system factory which will return the appropriate factory object depending upon the employee type and designation.
public class EmpSystemFactory
{
public IComputerFactory Create(EmpData emp)
{
IComputerFactory factory = null;
switch (emp.EmployeeType)
{
case EmployeeType.Permanent:
factory = emp.Designation == EmployeeDesignation.Manager ?
new ComputerMacBookFactory() :
new ComputerMacFactory();
break;
case EmployeeType.Contract:
factory = emp.Designation == EmployeeDesignation.Manager ?
new ComputerDellLaptopFactory() :
new ComputerDellFactory();
break;
}
return factory;
}
}
Add Client
Under the Client folder add EmpSystemManager class. This client will be responsible for giving us the exact string which we need.
public class EmpSystemManager
{
private readonly IComputerFactory _icf;
public EmpSystemManager(IComputerFactory iComputerFactory)
{
_icf = iComputerFactory;
}
public string GetSystemDetails()
{
var brand = _icf.SystemBrand().GetBrand();
var processor = _icf.SystemProcessor().GetProcessor();
var type = _icf.SystemType().GetSystemType();
return $"{brand} {type} {processor}";
}
}
Integrating the AbstractFactory and Client
static void Main(string[] args)
{
var employees = FillEmployees();
foreach (var emp in employees)
{
//gives back a factory obj
var factory = new EmpSystemFactory().Create(emp);
//pass the factory to the manager
var manager = new EmpSystemManager(factory);
//fill the details
emp.ComputerDetails = manager.GetSystemDetails();
}
PrintEmployees(employees);
Console.ReadLine();
}