Adapter

Adapter adapts interface of an existing class to another interface.

Wikipedia says

In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.

Real world example

Consider that you have some pictures in your memory card and you need to transfer them to your computer. In order to transfer them you need some kind of adapter that is compatible with your computer ports so that you can attach memory card to your computer. In this case card reader is an adapter. Another example would be the famous power adapter; a three legged plug can’t be connected to a two pronged outlet, it needs to use a power adapter that makes it compatible with the two pronged outlet. Yet another example would be a translator translating words spoken by one person to another

Object adapter example

Simple version

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ObjectAdapter implements Target
{
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee)
{
this.adaptee=adaptee;
}
public void request()
{
adaptee.specificRequest();
}
}
// Client end
public class ObjectAdapterTest
{
public static void main(String[] args)
{
Adaptee adaptee = new Adaptee();
Target target = new ObjectAdapter(adaptee);
target.request();
}
}

Specific example

Original log class

1
2
3
public interface LogFactory {
void debug(String tag,String message);
}

A new advanced log class

1
2
3
4
5
6
7
8
9
10
public interface NewLogger {
void newLogMethod(int priority, String message, Object ... obj);
}

public class NewLoggerImp implements NewLogger {
@Override
public void newLogMethod(int priority, String message, Object... obj) {
System.out.println(String.format("new logger record:%s",message));
}
}

Adapter to wrap the original log class

1
2
3
4
5
6
7
8
9
10
11
12
13
public class LogAdapter implements LogFactory {
private NewLogger newLogger;

public LogAdapter(NewLogger newLogger) {
this.newLogger = newLogger;
}

@Override
public void debug(String tag, String message) {
Objects.requireNonNull(newLogMethod);
newLogger.newLogMethod(1, message);
}
}

Client end

1
2
3
4
5
6
7
8
9
10
public class AdapterClient {
public void recordLog() {
LogFactory logFactory = new LogAdapter(new NewLoggerImp());
logFactory.debug("Test", "I am using new logger!");
}
}

LogAdapter: Adapter
NewLoggerImp: Adaptee
LogFactory: target

Applicability

Use the Adapter pattern when

  • you want to use an existing class without changing the source code, and its interface does not match the one you need
  • you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don’t necessarily have compatible interfaces
  • most of the applications using third party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code.

Reference

Java-design-patterns