In this article, as is clear from the title today is about the Adapter design pattern, the name of which can be guessed enables the cooperation of objects that do not match each other 🙂
Description and implementation method
More specifically, in the Adapter pattern, the idea is to make it possible for objects with incompatible interfaces to work together. It is useful, for example, in the use of newer versions of some libraries, eg when we used an old library, but a new library came out and we want to adapt this old one to this new one. Another task of the Adapter is also to pack the old interface into a new one.
In the real world, the adapter is like an adapter to the monitor plug, for example, I recently had to buy a new monitor and the monitor plug did not fit into the computer, so I had to go to the store for an adapter. The adapter has a very similar function in the programming world.
Structure
Let’s look at the UML diagram of the adapter pattern
It shows that the Rectangle class uses the Shape interface and the LegacyRectangle class uses the Rectangle class.
Example
The scheme of operation
Let’s take an example to show what the adapter is about:
class Adapter : IClientInterface
{
public void SomeMethod1()
{
var oldclass= new NewClass();
oldclass.SomeMethod2(); //Calling the SomeMethod2 method
}
}
public interface IClientInterface
{
void SomeMethod1();
}
class NewClass
{
public void SomeMethod2()
{
Console.WriteLine("Calling the SomeMethod2 method");
}
}
static void Main(string[] args)
{
Adapter adapter = new Adapter();
adapter.SomeMethod1(); //Calling the SomeMethod1 method
Console.ReadKey();
}
I did it on a very simple example, there is a new class and we want it to be compatible with the old class interface without changing the method names, I created for this purpose an adapter class that implements the IClientInterface interface, i.e. we have to create old methods in this class and so we do that and inside SomeMethod1() method create an instance of a new class (let’s not focus on the rules of pure code, it’s important to convey the idea of the adapter) and calls its method.
Notice what happened, we used the new class method, but in the Adapter class, which uses the names of the old class methods, this is more or less what the adapter does.
Result:
Phone models
Let’s do an example now that better applies to everyday life, let’s do an adapter for the new version of iphone from 6 to 7:
The iphone6 class looks like this:
interface Iiphone6
{
void ProtectedFromWater(bool ifprotected);
void SpeedWorking(string speed);
void SizeOfScreen(int inch);
}
class Iphone6 : Iiphone6
{
public void SizeOfScreen(int inch)
{
Console.WriteLine("Screen size in inches: " + inch);
}
public void SpeedWorking(string speed)
{
Console.WriteLine("IPhone speed: " + speed);
}
public void ProtectedFromWater(bool ifprotected)
{
Console.WriteLine("Is it protected from water? " + ifprotected);
}
}
And the iphone7 class like this:
interface Iiphone7
{
void PhoneIsProtectedFromWater(bool ifprotected);
void SpeedPhoneWorking(string speed);
void PhoneSizeScreen(int inch);
}
class Iphone7 : Iiphone7
{
public void PhoneSizeScreen(int inch)
{
Console.WriteLine("Screen size in inches: " + inch);
}
public void SpeedPhoneWorking(string speed)
{
Console.WriteLine("IPhone speed: " + speed);
}
public void PhoneIsProtectedFromWater(bool ifprotected)
{
Console.WriteLine("Is it protected from water? " + ifprotected);
}
}
We can see that the interfaces of these classes do not match, have different method names, method names in the iphone6 and iphone7 classes, also changed, and we want to use old method names, in which case we need to create an adapter that will be implementing methods with old names and in these methods he will call methods from the new class iphone7, it looks like this:
class IphoneAdapter : Iiphone6
{
Iiphone7 iphone7 = new Iphone7();
public void ProtectedFromWater(bool ifprotected)
{
iphone7.PhoneIsProtectedFromWater(ifprotected);
}
public void SizeOfScreen(int inch)
{
iphone7.PhoneSizeScreen(inch);
}
public void SpeedWorking(string speed)
{
iphone7.SpeedPhoneWorking(speed);
}
}
First, we create an instance of the iphone7 class with an abstract type, then we implement the methods from the iphone6 interface and in them we call methods from the new class.
In the client, in the “Main” method, we call it like this:
static void Main(string[] args)
{
Console.WriteLine("iphone6 parameters");
Iphone6 iphone6 = new Iphone6();
iphone6.ProtectedFromWater(true); //Is it protected from water? true
iphone6.SizeOfScreen(3); //Screen size in inches: 3
iphone6.SpeedWorking("Slow"); //IPhone speed: Slow
Console.WriteLine("\niphone7 parameters");
IphoneAdapter iphone6Adapter = new IphoneAdapter();
iphone6Adapter.ProtectedFromWater(true); //Is it protected from water? true
iphone6Adapter.SizeOfScreen(4); //Screen size in inches: 4
iphone6Adapter.SpeedWorking("Fast"); //IPhone speed: Fast
Console.ReadKey();
}
First, we call the old version of iphone6, then the Adapter class, which has old methods of the iphone6 class, in both cases works the same.
Result:
Change of the electricity system
This example had to be found, in this example we will switch from the Polish electricity system to the American one, this is well illustrated by the picture below.
Let’s move to the code, this example will look very much like the previous one with phones. Let’s start with the PolandElectricalSocket class, ie from the Polish electricity system.
public interface PolandPlugConnector
{
void giveElectricity();
}
public class PolandElectricalSocket : PolandPlugConnector
{
public void giveElectricity()
{
Console.WriteLine("Use electricity systems from Poland");
}
}
And let’s also see what the class from the American electricity system looks like.
public interface UKPlugConnector
{
void provideElectricity();
}
public class UKElectricalSocket : UKPlugConnector
{
public void provideElectricity()
{
Console.WriteLine("Use electricity systems from USA");
}
}
And let’s see the class of the adapter switching the Polish system to the American system.
public class PolandToUKPlugConnectorAdapter : PolandPlugConnector
{
private UKPlugConnector plug;
public PolandToUKPlugConnectorAdapter(UKPlugConnector plug)
{
this.plug = plug;
}
public void giveElectricity()
{
plug.provideElectricity();
}
}
And finally the customer
static void Main(string[] args)
{
Console.WriteLine("Switch on poland socket");
PolandElectricalSocket PolandPlugConnector = new PolandElectricalSocket();
PolandPlugConnector.giveElectricity();
Console.WriteLine("\nSwitch on USA socket");
PolandToUKPlugConnectorAdapter USAPlugConnector = new PolandToUKPlugConnectorAdapter(new UKElectricalSocket());
USAPlugConnector.giveElectricity();
Console.ReadKey();
}
You can see that it looks very much like the previous example. If you did an example with phones, I do not know if there is anything to be translated here.
Result
Relations with other design patterns
- The facade uses a new interface, the adapter uses the old interface.
- The adapter provides a different interface for the object. Proxy provides the same interface. The decorator provides an extended interface.
- The bridge is designed so that abstraction and implementation are independent of each other. Thanks to the adapter, unrelated classes are to cooperate with each other.
- The adapter is used to change the interface of an existing object. The decorator improves another object without changing its interface.
Summary
That’s all about Adapter 🙂.
Link to github with the whole code from this article: https://github.com/Slaw145/AdapterTutorial
This content also you can find on my blog http://devman.pl/programtech/design-patterns-adapter/
If you recognise it as useful, share it with others so that others can also use it.
Leave upvote and follow and wait for next articles :) .
In the next article, we will talk about the Decorator pattern.
And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂
– site on fb: Devman.pl-Sławomir Kowalski
– group on fb: DevmanCommunity
Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.
Hey @slawas, great post! I enjoyed your content. Keep up the good work! It's always nice to see good content here on Steemit! Cheers :)