An interface is a contract between itself and any class that implements it. This contract states that any class that implements the interface will implement the interface's properties, methods and/or events. An interface contains no implementation, only the signatures of the functionality the interface provides. An interface can contain signatures of methods, properties, indexers, and events.
Using interface-based design concepts provides loose coupling, component-based programming, easier maintainability, makes your code base more scalable and makes code reuse much more accessible because the implementation is separated from the interface.
The code below loads sample data that I created into the interfaces called IProductModel. There are two types of products, physical and digital. I then create a class object called Customer and populate it with test data. The purpose of the foreach is to loop through each product within the cart and execute ShipItem() which simulates the shipping by outputting a message.
static void Main()
{
List<IProductModel> cart = AddSampleData();
CustomerModel customer = GetCustomer();
foreach (IProductModel prod in cart)
{
prod.ShipItem(customer);
}
}
PhysicalProductModel
consists of signatures that are implemented from IProductModel
but then are expanded.
public class PhysicalProductModel : IProductModel
{
public string Title { get; set; }
public bool HasOrderBeenCompleted { get; private set; }
public void ShipItem(CustomerModel customer)
{
if (HasOrderBeenCompleted == false)
{
Console.WriteLine($"Simulating shipping {Title} to {customer.FirstName} in {customer.City}");
HasOrderBeenCompleted = true;
}
}
}
DigitalProductModel
consists of signatures that are implemented from IDigitalProductModel
but then are expanded.
public class DigitalProductModel : IDigitalProductModel
{
public string Title { get; set; }
public bool HasOrderBeenCompleted { get; private set; }
public int TotalDownloadsLeft { get; private set; } = 5;
public void ShipItem(CustomerModel customer)
{
if (HasOrderBeenCompleted == false)
{
Console.WriteLine($"Simulating emailing {Title} to {customer.EmailAddress}");
TotalDownloadsLeft -= 1;
if (TotalDownloadsLeft < 1)
{
HasOrderBeenCompleted = true;
TotalDownloadsLeft = 0;
}
}
}
}
Both models are implementing an interface according to their product type.
Within Program.cs
I populate the List<IProductModel>
:
private static List<IProductModel> AddSampleData()
{
List<IProductModel> output = new List<IProductModel>();
// Physical Products
output.Add(new PhysicalProductModel { Title = "RTX 3090" });
output.Add(new PhysicalProductModel { Title = "Dublin T-Shirt" });
output.Add(new PhysicalProductModel { Title = "SSD 1Tb" });
output.Add(new PhysicalProductModel { Title = "iPhone 15 Pro 5Tb" });
// Digital Products
output.Add(new DigitalProductModel { Title = "Lesson Source Code" });
output.Add(new DigitalProductModel { Title = "Game Key Activation" });
output.Add(new DigitalProductModel { Title = "Monthly Subscription Key" });
// Course Products
output.Add(new CourseProductModel { Title = "Programming For Beginners" });
return output;
}
This allows us to distinguish between different types of products. (e.g Physical, Digital, Course)
Each product has its own Model: PhysicalProductModel
, DigitalProductModel
, CourseProductModel
, therefore each model implements a corresponding interface in order to inherit signatures that are required for each product model to function.
ICustomerModel
IDigitalProductModel
IProductModel
Each interface is trying to capture similarities among unrelated classes without artificially forcing a class relationship.
An interface can also implement another interface. In this case, I have IProductModel
which is the master interface and IDigitalProductModel
implants it.
IProductModel
public interface IProductModel
{
// Signatures
string Title { get; set; }
bool HasOrderBeenCompleted { get; }
void ShipItem(CustomerModel customer);
}
IDigitalProductModel
public interface IDigitalProductModel : IProductModel
{
int TotalDownloadsLeft { get; }
}
The interface above uses the exact same signatures as IProductModel
but extends by adding TotalDownloadsLeft
property for digital products only.