Leverage the Adapter design pattern to map incompatible interfaces, increase code coverage, and reduce complexities in designs Design patterns are solutions to recurring problems and complexities in software design. Design patterns are categorized as Creational, Structural, or Behavioral. Creational patterns are used to create and manage the mechanism of creating instances of classes. Structural patterns are used to realize the relationships among the entities. Behavioral design patterns deal with object collaboration and delegation of responsibilities. The Adapter pattern is a structural design pattern that acts as a bridge between two interfaces that are incompatible. The term “Adapter” is used to represent an object that enables two mutually incompatible interfaces to communicate and collaborate. In essence, the Adapter pattern enables classes (that have incompatible interfaces) to work together and their objects communicate if need be. There are certain types of adapters that implement he interfaces of both the Target and the Adaptee. Such types of Adapters are known as Two-Way adapters. You also have two distinct types of adapters namely, Class Adapters and Object Adapters. While the former uses inheritance, the latter uses composition to fix incompatibility issues in your designs. You can use the adapter design pattern when you need to use a third-party library that is incompatible with the types you have in your application. The following is the list of the types that participate in a typical implementation of the Adapter pattern: Target Adapter Adaptee Client Let’s understand this with an example. Suppose two people who speak and understand different languages need to communicate — one may be French and the other German. So, these two persons can speak and understand only French and German respectively — not both. You would typically need someone (an interpreter) who knows both these languages to facilitate the communication. So, the person who can facilitate this communication acts as the adapter. This pattern falls under the structural category since you would use this pattern to structure the types in our application — typically this pattern can transform one interface into another. The Gang of Four defines the Adapter pattern as “Convert the interface of a class into another interface that the clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.” Let’s dig into some code now. Consider the following two classes. public class TargetA { public void DisplayA() { Console.WriteLine("TargetA"); } } public class TargetB { public void DisplayB() { Console.WriteLine("TargetB"); } } As you can see, the two classes are incompatible — they don’t have any common base either. The following code listing shows how the adapter classes look like. public interface ITargetAdapter { void ProcessData(); } public class AdapterA : ITargetAdapter { public TargetA targetA { get; set; } public void Process() { targetA.DisplayA(); } public AdapterA(TargetA obj) { targetA = obj; } } public class AdapterB : ITargetAdapter { public TargetB targetB { get; set; } public void Process() { targetB.DisplayB(); } public AdapterB(TargetB obj) { targetB = obj; } } Note that both the adapter classes have one common interface named ITargetAdapter that these classes implement. Each of the two adapter classes has an argument constructor that accepts a reference to an object of the respective target classes. The ITargetAdapter interface contains the declaration of the Process() method. This method is implemented by both the adapter classes — these methods invoke the Display() and the respective display methods of the target classes we implemented earlier. The following code listing illustrates how you can use these adapter classes. class Program { static void Main(string[] args) { ITargetAdapter adapter = new AdapterA(new TargetA()); adapter.Process(); adapter = new AdapterB(new TargetB()); adapter.Process(); Console.Read(); } As you can see in the above code snippet, we need to pass an instance of the respective target class to the constructor of the adapter class. I’ll present discussions on more design patterns in my forthcoming posts here. The Adapter design pattern can be a good choice when you would need to invoke legacy code in your applications. You can learn more on the Adapter design pattern from this article. Related content how-to How to use FastEndpoints in ASP.NET Core Take advantage of the free open-source FastEndpoints library to build fast and lean APIs in your ASP.NET Core applications. By Joydip Kanjilal Jul 11, 2024 7 mins Microsoft .NET C# Development Libraries and Frameworks how-to How to use Refit to consume APIs in ASP.NET Core Take advantage of Refit REST library to simplify API consumption and make your code cleaner, more efficient, and easier to maintain. By Joydip Kanjilal Jul 04, 2024 10 mins C# Microsoft .NET Software Deployment how-to When to use an abstract class vs. interface in C# Understanding the differences between an abstract class and interface is key to designing loosely coupled and extensible applications. By Joydip Kanjilal Jun 20, 2024 10 mins Small and Medium Business Microsoft .NET C# how-to 6 security best practices for ASP.NET Core Learn the best practices and built-in safeguards for preventing attacks and protecting sensitive data in your ASP.NET Core web applications. By Joydip Kanjilal Jun 07, 2024 6 mins C# Microsoft .NET Web Development Resources Videos