GofPatterns Gofpatterns





Structural Patterns  «Prev 

Adapter Pattern demonstrated in Java:

Adapter Pattern Diagram

Description:

In the adapter pattern, a wrapper class (known as the adapter) is used to translate requests from it to another class (the adaptee). An adapter provides specific interactions with an adaptee that are not offered directly by the adaptee.
The adapter pattern takes two forms.

  1. In the first form, a "class adapter" utilizes inheritance. The class adapter extends the adaptee class and adds the desired methods to the adapter. These methods can be declared in an interface (ie, the "target" interface).
  2. In the second form, an object adapter utilizes composition. The object adapter contains an adaptee and implements the target interface to interact with the adaptee.
Here is a simple example of a class adapter and an object adapter. First, we have an adaptee class named CelciusPresenter. It stores a temperature value in Celcius.
package com.java.structural.adapter;

public class CelciusPresenter {
 double temperatureInC;
 public CelciusPresenter() {
 }
 public double getTemperature() {
  return temperatureInC;
 }
 public void setTemperature(double temperatureInC) {
  this.temperatureInC = temperatureInC;
 }
}

Here is our target interface that will be implemented by our adapter. It defines actions that our adapter will perform.

package com.java.structural.adapter;
public interface TemperatureInfo {
 public double getTemperatureInF();
 public void setTemperatureInF(double temperatureInF);
 public double getTemperatureInC();
 public void setTemperatureInC(double temperatureInC);
}

TemperatureClassPresenter is a class adapter. It extends CelciusPresenter [the adaptee] and implements TemperatureInfo (the target interface). If a temperature is in Celcius, TemperatureClassPresenter utilizes the temperatureInC value from CelciusPresenter. Fahrenheit requests are internally handled in Celcius.


package com.java.structural.adapter;
// example of a class adapter
public class TemperatureClassPresenter extends CelciusPresenter 
implements TemperatureInfo {
 @Override
 public double getTemperatureInC() {
  return temperatureInC;
 }
 @Override
 public double getTemperatureInF() {
  return cToF(temperatureInC);
 }
 @Override
 public void setTemperatureInC(double temperatureInC) {
  this.temperatureInC = temperatureInC;
 }
 @Override
 public void setTemperatureInF(double temperatureInF) {
  this.temperatureInC = fToC(temperatureInF);
 }
 private double fToC(double f) {
  return ((f - 32) * 5 / 9);
 }
 private double cToF(double c) {
  return ((c * 9 / 5) + 32);
 }
}

TemperatureObjectPresenter is an object adapter. It is similar in functionality to TemperatureClassPresenter, except that it utilizes composition for the CelciusPresenter rather than inheritance.

package com.java.structural.adapter;
// example of an object adapter
public class TemperatureObjectPresenter implements TemperatureInfo {
 CelciusPresenter celciusPresenter;
 public TemperatureObjectPresenter() {
  celciusPresenter = new CelciusPresenter();
 }
 @Override
 public double getTemperatureInC() {
  return celciusPresenter.getTemperature();
 }
 @Override
 public double getTemperatureInF() {
  return cToF(celciusPresenter.getTemperature());
 }
 @Override
 public void setTemperatureInC(double temperatureInC) {
  celciusPresenter.setTemperature(temperatureInC);
 }
 @Override
 public void setTemperatureInF(double temperatureInF) {
  celciusPresenter.setTemperature(fToC(temperatureInF));
 }
 private double fToC(double f) {
  return ((f - 32) * 5 / 9);
 }
 private double cToF(double c) {
  return ((c * 9 / 5) + 32);
 }
}

The AdapterDemo class is a client class that demonstrates the adapter pattern. First, it creates a TemperatureClassPresenter object and references it via a TemperatureInfo reference. It demonstrates calls to the class adapter via the TemperatureInfo interface. After this, it creates a TemperatureObjectPresenter object and references it via the same TemperatureInfo reference. It then demonstrates calls to the object adapter.


package com.java.structural.adapter;
public class AdapterDemo {
 public static void main(String[] args) {
  System.out.println("class adapter test");
  TemperatureInfo tempInfo = new TemperatureClassPresenter();
  testTempInfo(tempInfo);
  // object adapter
  System.out.println("\nobject adapter test");
  tempInfo = new TemperatureObjectPresenter();
  testTempInfo(tempInfo);
 }
 public static void testTempInfo(TemperatureInfo tempInfo) {
  tempInfo.setTemperatureInC(0);
  System.out.println("temp in C:" + tempInfo.getTemperatureInC());
  System.out.println("temp in F:" + tempInfo.getTemperatureInF());
  tempInfo.setTemperatureInF(85);
  System.out.println("temp in C:" + tempInfo.getTemperatureInC());
  System.out.println("temp in F:" + tempInfo.getTemperatureInF());
 }
}

The console output of the execution of AdapterDemo is shown here.
class adapter test
temp in C:0.0
temp in F:32.0
temp in C:29.444444444444443
temp in F:85.0

object adapter test
temp in C:0.0
temp in F:32.0
temp in C:29.444444444444443
temp in F:85.0