We are now ready to move on to the Structural Design Patterns after learning about the Creational Design Patterns in the previous few posts. The first pattern in this category is the Adapter Design Pattern. Let's see what is this pattern is for and how is it implemented in C# and .Net.
Note: Code can be download at my Github
1. What is the Adapter Design Pattern?
The adapter design pattern is about getting the interface that you want from the other interface that you were given by the system. In software engineering, it's often to make the existing classes work with others without modifying the source code.
The adapter pattern convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
2. When to use the Adapter Design Pattern?
As the name suggests, we can take the real world adapter to explain when we need to use the Adapter Design Pattern. In different countries, electrical devices have different power requirements such as the voltage or the socket/plug type. So, if you are travelling to another country, an adapter is needed for your devices if the destination has different type of power requirements.
The same is applied in programming. There are many existing applications and some of them need to adapt to others. At this moment, the Adapter Design Pattern is needed to help existing code works with others without modifying the source code.
3. How to implement the Adapter Design Pattern?
Let's say that we have 2 applications, one is a Line class which can give you a line object and the other is a Point class which can draw a point. Your task is to get the line object and drawn a line in a client application without modifying the existing source code in the 2 applications. Therefore, you need to come up with a new design in the client to adapt the 2 applications to each other. Follow below steps to implement:
Step 1: Determine an "adaptee" class
Line class - we can also call it an "adaptee" which will need to be adapted to the other class.
public class Line { public int StartX { get; set; } public int StartY = 0; public int EndX { get; set; } public int EndY = 0; public Line (int startX, int endX) { StartX = startX; EndX = endX; } }
Step 2: Determine a target class
Point class - which is also referred as a target class because it is used to let others adapt to it.
public class Point { public int X { get; set; } public int Y { get; set; } public Point(int x, int y) { X = x; Y = y; } public void DrawPoint() { Console.WriteLine($"Draw a point at ({X},{Y})"); } }
Step 3: Create an Adapter class
Here is what we need to do for our task. Since the client is not able to update the existing Line and Point classes except to initialize them, we need to create another class in client to adapt the Line class to the Point class so that it can draw a line by drawing each point between the start and end points of the line.
public class LineToPointAdapter { private readonly Line _adaptee; public LineToPointAdapter(Line line) { _adaptee = line; } public void DrawLine() { int min = Math.Min(_adaptee.StartX, _adaptee.EndX); int max = Math.Max(_adaptee.StartX, _adaptee.EndX); for (int i = min; i <= max; i++) { Point p = new Point(i, _adaptee.StartY); p.DrawPoint(); } } }
From now, we can use this adapter class to draw a line in client.
class Program { static void Main(string[] args) { Line line = new Line(5, 2); LineToPointAdapter adapter = new LineToPointAdapter(line); Console.WriteLine($"---Steps to draw Line ({line.StartX}, {line.StartY})-({line.EndX}, {line.EndY})---"); adapter.DrawLine(); } }
Done! This is a simple example to help you understand how Adapter Design Pattern works and how to implement it as well. In this particular example, I actually simplified the problem by allowing to create a horizontal line object only. You are welcome to modify this to make it works for diagonal lines also.
I hope this article is helpful! Please let me know your thoughts by commenting below. See you next time!