An abstract factory is a design pattern that solves the problem of creating entire product families without specifying their concrete classes.
The client needs to basically be able to create variants of products through 'abstract factories' that expose their creational methods.
I have provided a demo. It isnt exactly the same implementation as you may want, but it demonstrates the concepts of the design pattern.
First define the abstraction that each product family will implement:
public interface IAbstractFactory { public IElectricCar GetElectricCarModel(); public INonElectricCar GetNonElectricCarModel(); }
Then, create each family of a products.
IAudiFactory:
public class IAudiFactory : IAbstractFactory { public IElectricCar GetElectricCarModel() { return new AudiElectricCar(); } public INonElectricCar GetNonElectricCarModel() { return new NonAudiElectricCar(); } }
IBMWFactory:
public class IBMWFactory : IAbstractFactory { public IElectricCar GetElectricCarModel() { return new BMWElectricCar(); } public INonElectricCar GetNonElectricCarModel() { return new NonBMWElectricCar(); } }
Each family will enable the creation of a product variant.
Create an interface for each variant:
IElectricCar:
public interface IElectricCar { public CarModel GetDetails(); }
INonElectricCar:
public interface INonElectricCar { public CarModel GetDetails(); }
This is the car class that will be created:
public class CarModel { public string Year; public string Make; public string Model; public string KiloMeters; }
Create implementation of non electric and electric cars creators of each car factory type.
public class AudiElectricCar : IElectricCar { public CarModel GetDetails() { return new() { Year = "2021", Make = "China", Model = "Audi electric A1", KiloMeters = "201" }; } } public class NonAudiElectricCar : INonElectricCar { public CarModel GetDetails() { return new() { Year = "2020", Make = "Rand1", Model = "AUDI None electric A1", KiloMeters = "20" }; } } public class BMWElectricCar : IElectricCar { public CarModel GetDetails() { return new() { Year = "2021", Make = "China", Model = "BMW electric A1", KiloMeters = "201" }; } } public class NonBMWElectricCar : INonElectricCar { public CarModel GetDetails() { return new() { Year = "2020", Make = "Rand1", Model = "BMW None electric A1", KiloMeters = "20" }; } }
Once you are done writing the abstraction and implementation of your design pattern, create the client logic.
class Client { INonElectricCar nonElectricCar; IElectricCar electricCar; public Client(IAbstractFactory factory) { electricCar = factory.GetElectricCarModel(); nonElectricCar = factory.GetNonElectricCarModel(); } public CarModel GetElectricCarDetails() { return electricCar.GetDetails(); } public CarModel GetNonElectricCarDetails() { return nonElectricCar.GetDetails(); } }
The above logic doesnt have to be the same, as long the code runs successfully. An example of consuming the client in logic in action:
Client client = new Client(new IBMWFactory()); CarModel carModel = client.GetElectricCarDetails(); Console.WriteLine(carModel.Model); CarModel carModel2 = client.GetNonElectricCarDetails(); Console.WriteLine(carModel2.Model);
abstract class IModifyVehiclecould bite you in the assinterface IModifyVehicle