← Back to Advanced Java Course | Chapter 6: Design Patterns | Lesson 7 of 14

Java Adapter Pattern

The Adapter pattern converts one class's interface into another interface client code expects, letting otherwise incompatible classes work together without modifying either one.

What is the Adapter Pattern?

The Adapter pattern converts the interface of an existing class into another interface that client code expects, letting classes with otherwise incompatible interfaces work together without modifying either one.

Example: What is the Adapter Pattern?

java
public class Main {
	interface Target { void request(); }
	static class Adaptee { void specificRequest() { System.out.println("Adaptee's own method"); } }
	static class Adapter implements Target {
		Adaptee adaptee = new Adaptee();
		public void request() { adaptee.specificRequest(); } // translates one interface to another
	}
	public static void main(String[] args) {
		Target t = new Adapter();
		t.request();
	}
}

Class Adapter vs Object Adapter

A class adapter uses inheritance to extend the adaptee directly, while an object adapter uses composition, holding a reference to the adaptee instance -- Java's single inheritance limits favor the object adapter approach in most cases.

Example: Class Adapter vs Object Adapter

java
public class Main {
	static class Adaptee { void specific() { System.out.println("specific()"); } }
	interface Target { void request(); }
	static class ObjectAdapter implements Target { // composition -- holds a reference
		Adaptee adaptee = new Adaptee();
		public void request() { adaptee.specific(); }
	}
	public static void main(String[] args) {
		new ObjectAdapter().request(); // Java favors this over class-adapter inheritance
	}
}

Adapting a Legacy Interface

Adapters are especially common when integrating with legacy code or a third-party library whose API doesn't match what the rest of an application expects, isolating that mismatch behind a single translation class.

Example: Adapting a Legacy Interface

java
public class Main {
	static class LegacyPrinter { void oldPrint(String s) { System.out.println("Legacy: " + s); } }
	interface ModernPrinter { void print(String s); }
	static class PrinterAdapter implements ModernPrinter {
		LegacyPrinter legacy = new LegacyPrinter();
		public void print(String s) { legacy.oldPrint(s); } // isolates the mismatch here
	}
	public static void main(String[] args) {
		ModernPrinter p = new PrinterAdapter();
		p.print("Hello");
	}
}

Adapting Data Formats

Beyond just renaming methods, an adapter can also convert data between formats or units entirely, such as translating XML to JSON or Fahrenheit to Celsius, while presenting a clean target interface to callers.

Example: Adapting Data Formats

java
public class Main {
	interface TemperatureReader { double celsius(); }
	static class FahrenheitSensor { double readFahrenheit() { return 98.6; } }
	static class TemperatureAdapter implements TemperatureReader {
		FahrenheitSensor sensor = new FahrenheitSensor();
		public double celsius() { return (sensor.readFahrenheit() - 32) * 5 / 9; } // converts units, not just names
	}
	public static void main(String[] args) {
		System.out.println(new TemperatureAdapter().celsius());
	}
}

Adapter vs Facade

Adapter and Facade both wrap other code, but Adapter exists to make one specific incompatible interface fit an expected one, while Facade exists to simplify access to an entire complex subsystem behind a single simplified interface.

Example: Adapter vs Facade

java
public class Main {
	interface Target { void request(); } // Adapter: makes ONE incompatible interface fit
	static class SubsystemA { void a() { System.out.println("A"); } }
	static class SubsystemB { void b() { System.out.println("B"); } }
	static class Facade { // Facade: simplifies access to a WHOLE subsystem
		void doEverything() { new SubsystemA().a(); new SubsystemB().b(); }
	}
	public static void main(String[] args) {
		new Facade().doEverything();
	}
}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.