Паттерн проектирования адаптера на Java

Адаптер – это один из структурных шаблонов проектирования, который используется для того, чтобы два несвязанных интерфейса могли взаимодействовать. Объект, который объединяет эти несвязанные интерфейсы, называется Адаптером.

Шаблон проектирования “Адаптер”

Один из отличных примеров использования шаблона проектирования “Адаптер” в реальной жизни – это зарядное устройство для мобильного телефона. Аккумулятор мобильного телефона требует 3 вольта для зарядки, но обычная розетка выдает либо 120 В (в США), либо 240 В (в Индии). Таким образом, зарядное устройство для мобильного телефона работает как адаптер между разъемом для зарядки мобильного телефона и розеткой. Мы попробуем реализовать многозонный адаптер с использованием шаблона проектирования “Адаптер” в этом учебнике. Итак, прежде всего, у нас будут два класса – Volt (для измерения вольт) и Socket (производящий постоянные вольты 120 В).

package com.journaldev.design.adapter;

public class Volt {

	private int volts;
	
	public Volt(int v){
		this.volts=v;
	}

	public int getVolts() {
		return volts;
	}

	public void setVolts(int volts) {
		this.volts = volts;
	}
	
}
package com.journaldev.design.adapter;

public class Socket {

	public Volt getVolt(){
		return new Volt(120);
	}
}

Теперь мы хотим создать адаптер, который может производить 3 вольта, 12 вольт и стандартные 120 вольт. Для этого сначала создадим интерфейс адаптера с этими методами.

package com.journaldev.design.adapter;

public interface SocketAdapter {

	public Volt get120Volt();
		
	public Volt get12Volt();
	
	public Volt get3Volt();
}

Двунаправленный шаблон адаптера

При реализации шаблона адаптера существуют два подхода – классовый адаптер и объектный адаптер – однако оба этих подхода производят одинаковый результат.

  1. Классовый адаптер – Эта форма использует наследование в Java и расширяет исходный интерфейс, в нашем случае класс Socket.
  2. Объектный адаптер – Эта форма использует композицию в Java, а адаптер содержит объект источника.

Шаблон проектирования адаптер – Классовый адаптер

Вот реализация подхода с классовым адаптером нашего адаптера.

package com.journaldev.design.adapter;

//Использование наследования для шаблона адаптера
public class SocketClassAdapterImpl extends Socket implements SocketAdapter{

	@Override
	public Volt get120Volt() {
		return getVolt();
	}

	@Override
	public Volt get12Volt() {
		Volt v= getVolt();
		return convertVolt(v,10);
	}

	@Override
	public Volt get3Volt() {
		Volt v= getVolt();
		return convertVolt(v,40);
	}
	
	private Volt convertVolt(Volt v, int i) {
		return new Volt(v.getVolts()/i);
	}

}

Шаблон проектирования адаптер – Реализация объектного адаптера

Вот реализация объектного адаптера нашего адаптера.

package com.journaldev.design.adapter;

public class SocketObjectAdapterImpl implements SocketAdapter{

	//Использование композиции для шаблона адаптера
	private Socket sock = new Socket();
	
	@Override
	public Volt get120Volt() {
		return sock.getVolt();
	}

	@Override
	public Volt get12Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,10);
	}

	@Override
	public Volt get3Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,40);
	}
	
	private Volt convertVolt(Volt v, int i) {
		return new Volt(v.getVolts()/i);
	}
}

Обратите внимание, что обе реализации адаптера практически идентичны и реализуют интерфейс SocketAdapter. Интерфейс адаптера также может быть абстрактным классом. Вот тестовая программа для использования нашей реализации паттерна проектирования адаптера.

package com.journaldev.design.test;

import com.journaldev.design.adapter.SocketAdapter;
import com.journaldev.design.adapter.SocketClassAdapterImpl;
import com.journaldev.design.adapter.SocketObjectAdapterImpl;
import com.journaldev.design.adapter.Volt;

public class AdapterPatternTest {

	public static void main(String[] args) {
		
		testClassAdapter();
		testObjectAdapter();
	}

	private static void testObjectAdapter() {
		SocketAdapter sockAdapter = new SocketObjectAdapterImpl();
		Volt v3 = getVolt(sockAdapter,3);
		Volt v12 = getVolt(sockAdapter,12);
		Volt v120 = getVolt(sockAdapter,120);
		System.out.println("v3 volts using Object Adapter="+v3.getVolts());
		System.out.println("v12 volts using Object Adapter="+v12.getVolts());
		System.out.println("v120 volts using Object Adapter="+v120.getVolts());
	}

	private static void testClassAdapter() {
		SocketAdapter sockAdapter = new SocketClassAdapterImpl();
		Volt v3 = getVolt(sockAdapter,3);
		Volt v12 = getVolt(sockAdapter,12);
		Volt v120 = getVolt(sockAdapter,120);
		System.out.println("v3 volts using Class Adapter="+v3.getVolts());
		System.out.println("v12 volts using Class Adapter="+v12.getVolts());
		System.out.println("v120 volts using Class Adapter="+v120.getVolts());
	}
	
	private static Volt getVolt(SocketAdapter sockAdapter, int i) {
		switch (i){
		case 3: return sockAdapter.get3Volt();
		case 12: return sockAdapter.get12Volt();
		case 120: return sockAdapter.get120Volt();
		default: return sockAdapter.get120Volt();
		}
	}
}

При запуске вышеуказанной тестовой программы мы получаем следующий вывод.

v3 volts using Class Adapter=3
v12 volts using Class Adapter=12
v120 volts using Class Adapter=120
v3 volts using Object Adapter=3
v12 volts using Object Adapter=12
v120 volts using Object Adapter=120

Диаграмма классов паттерна проектирования адаптера

Пример паттерна проектирования адаптера в JDK

Некоторые примеры паттерна проектирования адаптера, которые я легко нашел в классах JDK, включают;

  • java.util.Arrays#asList()
  • java.io.InputStreamReader(InputStream) (возвращает Reader)
  • java.io.OutputStreamWriter(OutputStream) (возвращает Writer)

Вот и все, что касается паттерна проектирования адаптера в Java.

Source:
https://www.digitalocean.com/community/tutorials/adapter-design-pattern-java