Adapter is a struc­tur­al design pat­tern that allows objects with incom­pat­i­ble inter­faces to collaborate.

Problem: an existing component offers functionality, but is not compatible with the new system being developed

Solution: the adapter pattern connects incompatible components

→ Also called wrapper

image.png

image.png

An adapter wraps one of the objects to hide the com­plex­i­ty of con­ver­sion hap­pen­ing behind the scenes. The wrapped object isn’t even aware of the adapter.

image.png

Definition: legacy system

Problems with legacy systems

with the same functionality is too high

the compiler is no longer available or source code has been lost

service and replaced with a new system

requirements

Comparison: adapter pattern vs. bridge pattern

image.png

public class ThermoAdapter implements ThermoInterface {
	private FahrenheitThermo thermo;
	public ThermoAdapter() {
		thermo = new FahrenheitThermo();
	}
	public double getTempC() {
		return (thermo.getFahrenheitTemperature() - 32.0) * (5.0 / 9.0);
	}
}

Structure

image.png

  1. The Client is a class that con­tains the exist­ing busi­ness logic of the program.
  2. The Client Inter­face describes a pro­to­col that other class­es must fol­low to be able to col­lab­o­rate with the client code.
  3. The Ser­vice is some use­ful class (usu­al­ly 3rd-party or lega­cy). The client can’t use this class direct­ly because it has an incom­pat­i­ble interface.
  4. The Adapter is a class that’s able to work with both the client and the ser­vice: it imple­ments the client inter­face, while wrap­ping the ser­vice object. The adapter receives calls from the client via the adapter inter­face and trans­lates them into calls to the wrapped ser­vice object in a for­mat it can understand.
  5. The client code doesn’t get cou­pled to the con­crete adapter class as long as it works with the adapter via the client inter­face. Thanks to this, you can intro­duce new types of adapters into the pro­gram with­out break­ing the exist­ing client code. This can be use­ful when the inter­face of the ser­vice class gets changed or replaced: you can just cre­ate a new adapter class with­out chang­ing the client code.”

Class Adapter

This imple­men­ta­tion uses inher­i­tance: the adapter inher­its inter­faces from both objects at the same time. Note that this approach can only be imple­ment­ed in pro­gram­ming lan­guages that sup­port mul­ti­ple inher­i­tance.

image.png

The Class Adapter doesn’t need to wrap any objects because it inher­its behav­iors from both the client and the ser­vice. The adap­ta­tion hap­pens with­in the over­rid­den meth­ods. The result­ing adapter can be used in place of an exist­ing client class.

<aside>

Applicability

TEXT

<aside>

How to Implement

  1. Make sure that you have at least two class­es with incom­pat­i­ble interfaces
    1. A use­ful ser­vice class, which you can’t change (often 3rd-party, lega­cy or with lots of exist­ing dependencies).
    2. One or sev­er­al client class­es that would ben­e­fit from using the ser­vice class.
  2. Declare the client inter­face and describe how clients com­mu­ni­cate with the service.
  3. Cre­ate the adapter class and make it fol­low the client inter­face. Leave all the meth­ods empty for now.
  4. Add a field to the adapter class to store a ref­er­ence to the ser­vice object. The com­mon prac­tice is to ini­tial­ize this field via the con­struc­tor, but some­times it’s more con­ve­nient to pass it to the adapter when call­ing its methods.
  5. One by one, imple­ment all meth­ods of the client inter­face in the adapter class. The adapter should del­e­gate most of the real work to the ser­vice object, han­dling only the inter­face or data for­mat conversion.
  6. Clients should use the adapter via the client inter­face. This will let you change or extend the adapters with­out affect­ing the client code.” </aside>