I didn't know what design patterns were until I read a book by Wrox publications titled "Design Patterns with VB.NET". Must be something interesting I thought. It wasn't. Well, not for a first time reader/programmer. And .NET wasn't a platform which I had to rely on to learn about patterns either. I was a pure C++ guy earlier and I had an exposure to OOP that way. But after reading this, I never knew OOP turned out to be this dense and complicated.
Was there a new concept in OOP all together? Yes and no. What .NET (and other platforms around that time) had to offer at the time was something new which I had not yet discovered was the idea of interfaces wherein you define a skeleton of methods or properties. A class that "implements" this interface should have those methods or properties. But I truly appreciated the idea of interfaces when I came to discover that you can use an instance of an "interface" like an object. The underlying instance of this object can be any class that implements the interface.
Interfaces have a lot to do with the whole subject of design patterns. But here I wish to demonstrate a simple example that made me actually appreciate the idea of interfaces. This project was for a Dell client. It had to deal with a mass emailing to customers about their payments. There were two types of customers - small & medium business group of customers (SMBC) & large business group (LBC) of customers. The message we had to compose depended on the type of customer. So on the first iteration I thought we should have two classes to represent each type of customer. (Remember I am not implementing a design pattern here.) But then depending on the customer type, I had to initialize the appropriate class. So this code would be seated inside an if
condition. However all I had to do was call one particular method to compose/send the mail. This method had the same functionality except depending on the class instantiated, it has to do different things. So I employed the concept of interfaces. Here is a basic outline for the code (C#) to get started:
Interface ICustomerEmailer
{
void Compose();
void Send();
}
public abstract class Customer
{
protected string CustID, Name, Message;
protected BusinessType CustType;
protected Customer(string CustID)
{
}
protected void Send()
{
Console.WriteLine("Sent mail to customer {0} ({1})", this.Name, this.CustType);
Console.WriteLine("Message : {0}", this.Message);
}
}
public class SMBC : Customer, ICustomerEmailer
{
public SMBC(string CustID) : base(CustID)
{
}
public void Compose()
{
this.Message = "Thankyou Mr/Mrs " + this.Name + ".
Hope you enjoy your SMBC package";
}
public void Send()
{
base.Send();
}
}
public class LBC : Customer, ICustomerEmailer
{
public LBC(string CustID) : base(CustID)
{
}
public void Compose()
{
this.Message = "Thankyou Mr/Mrs " +
this.Name + ". Hope you enjoy your LBC package";
}
public void Send()
{
base.Send();
}
}
In my main routine, and within a loop that iterates through customer ids (which I am supposed to send mail to), you'll find code like this:
public static void Main()
{
.
.
.
foreach(string ID in CustomerIDs)
{
ICustomerEmailer customer;
if (GetCustType(ID) == BusinessType.SMBC)
customer = new SMBC(ID);
else
customer = new LBC(ID);
customer.Compose();
customer.Send();
}
}
Notice how I make calls to Compose()
and Send()
. But if you happen to look at the output, you'll understand what is happening internally. This is a nice way to make your code look short and more easy to read. Anyone can grasp the overall process flow by looking at this code. I could in fact do away with the if
-else
block and instead call another method that creates the appropriate customer appropriately. If I did that, my application becomes easier to maintain. Suppose a third customer type comes, I can create a class to represent that customer and then make appropriate changes in this method to return the appropriate customer. My interface instance will do the job of sending the mail to the customer appropriately.
So there you go, interfaces!!!