Introduction
In the real world, we all are familiar with an electric outlet. Every country has its own style of electric outlets. That's why smartphone manufacturers makes a different style of charging adapters which are specific to the country. One great example would be Apple's Hyperdrive. It connects so many devices to a single USB port. Here, hyperdrive is acting as an Adapter.
The adapter also is known as a wrapper. cause it wraps some object that can be used by different objects.
Let's see UML first.
- The client is basically the class who wants to use the pattern. The calling class.
- Now the client wants to have Specific_request() which can only be served by Adaptee class, we can directly have a HAS-A relationship and be done with it. but the problem lies when there is another specific_request which is served by let's say Adaptee2 class, in this case, we have to make another HAS-A relationship and this could reoccur with every new requirement.
To deal with this, we can abstract a requirement and let abstraction handle delegation of a request made by the client. In the above UML, it is handled by the ITarget interface
Let's jump into the coding.
Example
Let's say our application reads data from an XML file and it serves the purpose for today. Tomorrow, if we would like our application to support JSON, then what?
Let's solve this problem with an Adapter design pattern.
This is how our UML would look:
Let's create an interface ITarget which will be called by our client.
- public interface ITarget
- {
- string GetDetails();
- }
Now our Adapter, which will implement ITarget: this class also has IEmployeeDetails interface: this interface will be implemented by both of our XML & JSON Adaptees to keep similar architecture in both of the classes, so our client code won't change.
- using AdapterDesignPattern.Adaptees;
-
- namespace AdapterDesignPattern.Target
- {
- public class Adapter : ITarget
- {
- public IEmployeeDetails Data;
- public Adapter(IEmployeeDetails data)
- {
- this.Data = data;
- }
- public string GetDetails()
- {
- return Data.GetData();
- }
- }
- }
Let's create an IEmployeeDetails interface:
- public interface IEmployeeDetails
- {
- string GetData();
- }
An employee class and an entity class
- public class Employee
- {
- public int EmpCode { get; set; }
- public string EmpName { get; set; }
- }
An adaptee class to load xml data. For now, we can generate data from code itself.
- using AdapterDesignPattern.Adaptees;
- using System.Collections.Generic;
- using System.IO;
- using System.Xml;
- using System.Xml.Serialization;
-
- namespace AdapterDesignPattern
- {
- public class XMLAdaptee : IEmployeeDetails
- {
- public string GetData()
- {
- List<Employee> Employees = new List<Employee>() {
- new Employee(){
- EmpCode = 1,
- EmpName = "Alex"
-
- },new Employee(){
- EmpCode = 2,
- EmpName = "Martin"
-
- },new Employee(){
- EmpCode = 3,
- EmpName = "Gloria"
- }
- };
- var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
- var serializer = new XmlSerializer(Employees.GetType());
- var settings = new XmlWriterSettings(); settings.Indent = true;
- settings.OmitXmlDeclaration = true;
- using (var stream = new StringWriter())
- using (var writer = XmlWriter.Create(stream, settings))
- {
- serializer.Serialize(writer, Employees, emptyNamepsaces);
- return stream.ToString();
- }
- }
- }
- }
Now our JSON adaptee:
- using Newtonsoft.Json;
- using System.Collections.Generic;
-
- namespace AdapterDesignPattern.Adaptees
- {
- public class JSONAdaptee : IEmployeeDetails
- {
- public string GetData()
- {
- List<Employee> Employees = new List<Employee>() {
- new Employee(){
- EmpCode = 1,
- EmpName = "Alex"
-
- },new Employee(){
- EmpCode = 2,
- EmpName = "Martin"
-
- },new Employee(){
- EmpCode = 3,
- EmpName = "Gloria"
- }
- };
- return JsonConvert.SerializeObject(Employees);
- }
- }
- }
Last but not least, our caller: class program:
- using AdapterDesignPattern.Adaptees;
- using AdapterDesignPattern.Target;
- using System;
-
- namespace AdapterDesignPattern
- {
- class Program
- {
- static void Main(string[] args)
- {
- IEmployeeDetails getXML = new XMLAdaptee();
- IEmployeeDetails getJSON = new JSONAdaptee();
-
-
- ITarget EmployeesDetails = new Adapter(getXML);
-
-
-
- Console.WriteLine(EmployeesDetails.GetDetails());
- }
- }
- }
Output for XML data:
Output for JSON data, just uncomment the above line in the code.
Perfect! I sincerely hope you enjoyed this blog and that you're inspired to apply what you've learned to your own applications. Thank you.
Happy coding.
Connect with me: