Published: 08 Oct 2008
By: Granville Barnett
Download Sample Code

In this part of the design patterns series we will look at the adapter pattern.

Contents [hide]

Introduction

When you have an existing API that is heavily reliant on certain interfaces within it and a newer side-by-side (SxS) API comes into production that is reliant on very similar interfaces what do you do? You can’t throw the old code away as the bulk of your system is legacy code. However, you would like to use the more optimized algorithms presented in the newer API. No doubt you will go away and traverse various articles on the internet and those in a library to arrive at something called the adapter pattern. In this article we will be looking at the object adapter as the type adapter requires multiple inheritance.

The adapter pattern allows us to change the interface of a type to something that a client expects. If there is anything you take from this article the previous sentence would be a prime candidate, although I implore you to read on.

Design Patterns Series

  • Part 1 Learn how to design more robust and maintainable code by incorporating design patterns into your software projects.
  • Part 2 This part shows the observer design pattern.
  • Part 3 In this part you will learn about the factory pattern.
  • Part 4 This part of the design patterns covers the singleton pattern.
  • Part 5 In this part of the design patterns series we investigate the command pattern and its uses.
  • Part 6 In this part of the design patterns series we will look at the adapter pattern.
  • Part 7 In this part of the design patterns series we will take a look at the template pattern.
  • The adapter pattern

    We mentioned shortly ago that the adapter pattern changes the interface of a type to something that the client expects, how on earth can we do that? The adapter pattern is really very simple, however, before we proceed its best that we look at a few of the major roles within the adapter pattern.

    There are four roles within the adapter pattern: client, adapter, adaptee, and the target interface. The client is a pseudoname for something that expects a specific interface (or type). We could for the purposes of simplicity state that the client is an alias for a method which expects as its parameter a type that implements a specific interface. As another example the client may need to collaborate with a type later on that is required to implement a specific interface. Next on the list is the big one – the adapter. What does the adapter do? Well, it wraps the adaptee up (explained shortly) and implements the interface the client expects. The adapter also delegates its work to the adaptee. An adaptee is the type that we want to use with the new code but we can’t because it doesn’t adhere to some behavior (as defined in an interface etc) that the client expects. Finally the target interface is the name given to the interface that the client expects. Don’t worry if all these roles have lost you at the moment, we will illustrate them soon via the use of a simple example scenario.

    The scenario

    The example to use for this pattern was really quite simple to think of as the problem is very common for anyone who travels abroad. The problem is that of plug sockets, namely that the UK plugs have three pins, and the continental (European, US) have two pins. For UK nationals (and others) that travel abroad this means that all our electrical devices like, for example mobile phone chargers, laptop power adapters and so on are pretty much useless. Fortunately for us, and for the rest of the world there exists adapters to make a three pin plug compatible with a two pin power source and vice versa for our international friends looking to dawn the UK shores. For this simple scenario let’s assume that we’ve taken only a few of our family to a beautiful resort someplace in the south of France. There is one problem though – the other family members stranded in the UK would like to know how we are getting on with our nice holiday. The problem we have is that the battery in our mobile phone has died and we only have a UK three pin adapter. Oh dear…

    Rest assured though that a quick stroll down to the local supermarket has brought with it the purchase of a three-to-two pin adapter. Now we can phone home. Let’s go ahead and model this scenario using the adapter pattern.

    Mapping the scenario to the roles within the adapter pattern

    First let us define two interfaces, each of which contain the same method name and prototype. These interfaces will be called ITwoPinPlug, and IThreePinPlug. Both interfaces define a method named Utilize. We will also define a few types: TwoPinPlug, and ThreePinPlug. Each plug implements the appropriate interface.

    To keep the sample code concise and to the point we will focus on the plugs and how we can adapt each to use the others respective power source. For this we will require two adapters: TwoPinPlugAdapter, and ThreePinPlugAdapter. The adapters will be composed of the correct respective plug type as well as implementing the opposing plugs interface.

    The role of the TwoPinPlugAdapter, and the ThreePinPlugAdapter are indeed adapters. The adapters will implement one of the target interfaces – either ITwoPinPlug, or IThreePinPlug. The adaptee’s are the plugs that we want to change the interface of.

    Figure 1: UML of our design

    UML of our design

    Now we are familiar with the design we will now present the implementation.

    Listing 1: ITwoPinPlug.cs

    Listing 2: IThreePinPlug.cs

    Listing 3: TwoPinPlug.cs

    Listing 4: ThreePinPlug.cs

    Listing 5: TwoPinPlugAdapter.cs

    Listing 6: ThreePinPlugAdapter.cs

    Listing 7: TwoPinSource.cs

    Listing 8: ThreePinSource.cs

    Listing 9: Program.cs

    If you run the project you will see the following output:

    Figure 2: Output of the example

    Output of the example

    The example scenario presented is very simple in that the interfaces described contain the same methods of which both plug types implement, but what if the interfaces varied? You should only support the methods of the target interface that your adaptee type(s) know how to deal with. As a result you may find yourself declaring that the adaptee within the adapter doesn’t support a particular method defined in the target interface. This is of course is perfectly reasonable.

    Consider a linked list with AddHead and AddTail operations. Furthermore, consider that we have a client that requires something that implements an interface IStack which declares the methods Push and Pop. In this particular example the adapter would implement IStack as the target interface with the adaptee being a linked list. In the Push method within the adapter type we would call the AddTail method, and in the Pop method we would call the RemoveTail method of the adaptee.

    Summary

    In this part of the design pattern series we have looked at the adapter pattern – a pattern that changes the interface of a type. We have identified and discussed the roles of the client, adapter, adaptee, and target interface. The culmination of our efforts led us to apply the adapter pattern to a simple plug scenario.

    Acknowledgements

    I would like to thank Jon Skeet [1] for reviewing this article and also providing further examples of the adapter pattern.

    [1] http://msmvps.com/blogs/jon_skeet/

    <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Granville Barnett

    Sorry, no bio is available

    This author has published 32 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    Introduction to StructureMap
    Have you heard of StructureMap, generally know what it’s for, and want to know how to get started qu...
    DI Patterns: Constructor Injection
    In this article, an excerpt from the book "Dependency Injection in .NET", we will take a detailed lo...
    The Command Pattern
    In this article I will provide a quick refresher on what the command pattern is used for, how it wor...
    TypeMock’s Arrange-Act-Assert
    Brian Mains discusses how to implement the Arrange-Act-Assert pattern in TypeMock.
    Key Process Patterns
    This article, based on chapter 2 of Specification by Example, presents effective patterns for softwa...

    You might also be interested in the following related blog posts


    Learn design patterns from real projects: JBoss case study (Part 1). read more
    Designing a Windows 8 Metro style app starting from an existing Windows Phone app Design Case Study Part 1 read more
    Oredev Wrap-Up read more
    Introducing SharePoint 2010 Training at U2U read more
    The Underground at PDC read more
    12 ASP.NET MVC Best Practices read more
    Screencast Whats new in the Entity Data Model Designer in VS2010 read more
    What needed to be monitored to get better Governance read more
    SharePoint 2010 Workflow read more
    Formatting Text in RadControls for WinForms Q3 2009 read more
    Top
     
     
     

    Please login to rate or to leave a comment.