Introduction
In our day to day lives, we learn new things. Similarly, in programming, we want to keep ourselves updated and learn every new feature. Learning a new thing is good but it is only beneficial for you as long as you implement it in your application. Thus, this article is about one of the topics that every programmer knows very well but they don’t know how to implement and benefit from it.
Interface
According to MSDN, An interface contains only the signatures of methods, properties, events or indexers. A class or struct that implements the interface must implement the members of the interface that are specified in the interface definition.
I must say everybody who has come to read this article has probably gone through the above definition once or several times to understand what interface is and how to use interface. But a few of them are not able to reap the benefits or aren't able to implement it in their daily lives. Let’s understand this with an example:
Create a public class MessageService which consists of a public method SendMessage. The MessageService class contains the business logic of SendingMessage to some other person.
- public class MessageService
- {
- public void SendMessage()
- {
-
- }
- }
Now, we can consume the MessageService class into another class NotificationSystem by creating object of the MessageService class into it and invoking the SendMessage method.
- public class NotificationSystem
- {
- private MessageService messageService;
- public NotificationSystem()
- {
- messageService = new ConsoleApp.MessageService();
- }
- public void NotifyUser()
- {
- messageService.SendMessage();
- }
- }
So far, the above code looks good and this is the way we use it to consume certain classes into another class in our day to day lives, but there is a problem with the above code - the NotificationSystem class has a direct dependency with the MessageService class, which means they are tightly coupled.
You must have heard several times that a system should be loosely coupled. To understand why a system should be a loosely coupled, let's consider a scenario.
- In the current system, there are several classes which consume the MessageService class to SendMessage to the customers.
- In the future, there might be a change in requirement where there are different MessageServices which are used to send messages to the customers.
- The possible solution based on your current design pattern is to create the new MessageService class and change the implementation in each and every class where the new Message service is required.
In the last step of the above scenario, you found that replacing the implementation of MessageService class in each and every class is a bit tedious job and also, if there is a large number of classes in which you have to change the implementation, there might be a possibility that your code may get inconsistent.
Also, you can see that each MessageService class has the same functionality; i.e., SendMessage; considering this point, let's resolve the above scenario using an interface.
First, create an interface IMessageService as below,
- interface IMessageService
- {
- void SendMessage();
- }
Now, implement the interface IMessageService into the MessageService class
- public class MessageService : IMessageService
- {
- public void SendMessage()
- {
-
- }
- }
Now, the major and most important change that needs to be done is into the NotificationSystem class
- public class NotificationSystem
- {
- private IMessageService messageService;
-
- public NotificationSystem()
- {
- messageService = new ConsoleApp.MessageService();
- }
- public void NotifyUser()
- {
- messageService.SendMessage();
- }
- }
Here, instead of Private MessageService object, we created a IMessageService object and in the constructor method of the NotificationSystem, we created an instance of the MessageService class into the messageService object. Rest of the code is same.
Now, see how the above implementation of interface resolved our problem.
- There is no direct coupling between the NotificationSystem class and MessageService. The IMessageService interface comes in between both classes and decouples these.
- It resolves our scenario problem. Now, we only need to implement the IMessageService class into the newly created MessageServices and replace the instance of the newly created method into the constructor of every class.
There are several other benefits of using Interfaces which I’ll try to cover in my upcoming articles. I hope, the above example gave you a better understanding of the implementation of interface into a real world scenario.