Prerequisite - A little Programming Knowledge would be great
Interface as a Concept – Talking in general terms, Interface as we all know has a very simple meaning it acts as a medium between two Media. Let’s take an example for what I specifically mean by the statement made.
- A Display Monitor – This monitor acts as an interface between humans operating on it and the CPU. We really do not care how the operation is being performed behind the scene like how things are displayed how clicking on a button gives you whatever is the desired result. In short we really don’t care about its internal functionalities or structure. Hence, it’s a layer of abstraction.
- An ATM Machine – A machine that enables you to get cash any time through a debit card. This machine is also an interface between you and the bank. Again in this case we really don’t care about the internals of the machine and how the whole process takes place which ultimately dispenses out the cash (if it’s available:-P).
OOP is strongly based on the concept of properties and state of the real world object which lead to the concept of interfaces in OOP. Now,
Interface as a keyword - An interface contains definitions for the most abstracted related functionalities that a class or a struct can implement. Interfaces can implement other interfaces. Interfaces cannot be initialized directly as they do not have a definition for members, they should be implemented by either a class or structure.
Using an Interface in our programming has lot of advantages:-
- Loose Coupling – Let’s try to concentrate on the word “coupling”. Here I am going to take the word as couple. Couple is of two right? Husband and wife. Now consider, if there are multiple husbands and multiple wife that are dependent on each other in some manner then just think about the havoc that will happen. I guess now it will be lot easier to understand the concept (laughs) .Every class that has to be created must have a single responsibility. The case of multiple wives and husband comes into picture when responsibilities of a class is spread around other classes or the concerns are spread across. Let’s have a look at a piece of code:-
Tight Coupling:-
class CustomerRepository
{
private readonly Database database;
public CustomerRepository(Database database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
class Database
{
public void AddRow(string Table, string Value)
{}
}
Loose Coupling:-
class CustomerRepository
{
private readonly IDatabase database;
public CustomerRepository(Database database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
interface IDatabase
{
void AddRow(string Table, string Value);
}
class Database: IDatabase
{
public void AddRow(string Table, string Value)
{}
}
- Hides implementation details of objects – Referencing the ATM Machine and Display Monitor example, let’s talk about the WCF Services. While we create an API we normally declare the method signature inside and interface and decorate it with an attribute ServiceContract. The Benefit – The client using this service is exposed via the Interface and not the actual class, keeping the client away from the actual implementation of the API. This serves the security concerns and makes the code more maintainable-How? Whenever there is a change in the API the interface doesn’t needs to be changed, only the implantation will be modified. The client code does not get affected.
- Treat different types in the Same Way – Nowadays, We all carry smartphones, smarter in some way or the other than other models in terms of features. The phones still serves the basic/fundamental purpose and that’s calling. While you get a call it rings to notify that you have a call to receive. So, every phone rings some just beep-beep, some polyphonic and some mp3 music. Let’s have a look at a piece of code.
interface IRingable
{
Public Sound Ring();
}
class SmartPhone: IRingable
{
public Sound Ring();
{
return PlayMp3Music();
}
}
class SemiSmartPhone: IRingable
{
public Sound Ring();
{
return PolyPhonicMusic();
}
}
class BasicPhone: IRingable
{
public Sound Ring();
{
return 8BitMusic();
}
}
class Main
{
public static void Main(string[] args)
{
List<IRingable> phones = new List<IRingable>();
IRingable htc = new SmartPhone();
Phones.Add(htc);
IRingable samsung = new SemiSmartPhone();
Phones.Add(samsung);
IRingable nokia = new BasicPhone();
Phones.Add(nokia);
foreach(IRingable phone in Phones)
{
phone.Ring();
}
}
}
Interface enabled me to treat all the types of phones in the same way. As Interface abstracted one of the fundamental behavior of a phone.
- Helps in making an application open for extension – Abiding to the SOLID Principles the O – Open for extension and close for modification, Let’s talk about an application which can sort a list of integers as per user’s preferences and also let there be a provision that a user can create his/her own sorting algorithm and just plug it into the application. Let’s see how:-
interface ISorting
{
bool execute(IList<int> numbers);
}
class InsertionSort: ISorting
{
public bool execute(List<int> numbers)
{
System.out.println("Executing InsertionSort");
return true;
}
}
class BubbleSort: ISorting
{
public bool execute(List<int> numbers)
{
System.out.println("Executing BubbleSort");
return true;
}
}
class RedixSort: ISorting
{
public bool execute(List<int> numbers)
{
System.out.println("Executing RedixSort");
return true;
}
}
class CustomSort: ISorting
{
public bool execute(List<int> numbers)
{
System.out.println("Executing CustomSort");
return true;
}
}
class Context {
private ISorting SortingStrategy;
public Context(ISorting Sortingstrategy)
{
this. SortingStrategy = Sortingstrategy;
}
Public bool executeStrategy(List<int> numbers)
{
return this.SortingStrategy.execute(numbers);
}
}
class StrategyExample {
public static void main(String[] args)
{
Context context;
context = new Context(new InsertionSort ());
bool resultA = context.executeStrategy(new List<int>(9,8,7,6,5,4,3,2,1));
context = new Context(new BubbleSort ());
bool resultB = context.executeStrategy(new List<int>(9,8,7,6,5,4,3,2,1));
context = new Context(new RedixSort ());
bool resultC = context.executeStrategy(new List<int>(9,8,7,6,5,4,3,2,1));
Console.WriteLine("Result A : " + resultA );
Console.WriteLine("Result B : " + resultB );
Console.WriteLine("Result C : " + resultC );
}
}
As you might have observed that we were able to put new strategy to sort the list and use it as per requirement. Oops, we just learned strategy pattern.
- Happy Coding.