← Назад к вопросам

Что такое паттерн Адаптер (Adapter)?

2.0 Middle🔥 111 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое паттерн Адаптер (Adapter)?

Паттерн Адаптер (Adapter) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами взаимодействовать друг с другом. Он выступает в роли "переводчика" или "конвертера" между двумя компонентами, которые изначально не могли работать вместе из-за различий в их API (Application Programming Interface). В мире Android разработки, особенно при работе с библиотеками, сторонними сервисами или при интеграции legacy-кода, адаптер является одним из наиболее часто используемых и практичных паттернов.

Основная идея и аналогия

Представьте ситуацию: у вас есть розетка европейского типа (круглые отверстия) и устройство с американской вилкой (плоские штыри). Они несовместимы напрямую. Для решения проблемы вы используете переходник (адаптер), который преобразует одну форму подключения в другую, позволяя устройству работать. Точно так же программный адаптер преобразует интерфейс одного класса в интерфейс, ожидаемый другим классом.

Типы адаптеров

Существует две классические реализации этого паттерна:

  1. Адаптер объектов (Object Adapter): Использует композицию. Адаптер содержит или наследует от адаптируемого объекта (Adaptee) и реализует целевой интерфейс (Target).
  2. Адаптер классов (Class Adapter): Использует множественное наследование (если язык поддерживает). Адаптер наследует одновременно от Adaptee и Target. В Java и Kotlin, где нет множественного наследования классов, этот тип менее распространен, но может быть эмулирован через наследование и интерфейсы.

Ключевые участники (роли)

  • Target (Цель): Интерфейс, который ожидает клиентская система. Адаптер должен реализовать этот интерфейс.
  • Adaptee (Адаптируемый): Существующий класс или объект с несовместимым интерфейсом, который нужно интегрировать.
  • Adapter (Адаптер): Класс, который реализует интерфейс Target и "переводит" запросы от клиента к Adaptee.
  • Client (Клиент): Система или класс, который работает через интерфейс Target и использует адаптер для взаимодействия с Adaptee.

Пример реализации в Kotlin (Object Adapter)

Рассмотрим классический пример из теории: у нас есть старая система, которая рисует прямоугольники (LegacyRectangle), но новый клиент ожидает работу через интерфейс Shape, который имеет метод draw().

// Target - интерфейс, ожидаемый клиентом
interface Shape {
    fun draw(x1: Int, y1: Int, x2: Int, y2: Int)
}

// Adaptee - существующий, но несовместимый класс
class LegacyRectangle {
    fun display(x: Int, y: Int, w: Int, h: Int) {
        println("LegacyRectangle: drawing at ($x, $y) with width $w and height $h")
    }
}

// Adapter - преобразует интерфейс LegacyRectangle в интерфейс Shape
class RectangleAdapter(private val legacyRect: LegacyRectangle) : Shape {
    override fun draw(x1: Int, y1: Int, x2: Int, y2: Int) {
        // Адаптация: преобразование координат двух точек в координату и размеры
        val width = x2 - x1
        val height = y2 - y1
        legacyRect.display(x1, y1, width, height)
    }
}

// Client - работает только с интерфейсом Target
fun main() {
    val legacyRect = LegacyRectangle()
    val adapter: Shape = RectangleAdapter(legacyRect)

    // Клиент вызывает метод draw(), не знающий о LegacyRectangle
    adapter.draw(10, 20, 50, 60)
}

Практическое применение в Android

В Android разработке паттерн Адаптер встречается буквально на каждом шагу, и чаще всего он неявно реализован в стандартных компонентах:

  • RecyclerView.Adapter: Самый очевидный и важный пример. Он адаптирует ваши данные (список объектов List<YourData>) к интерфейсу, который ожидает RecyclerView для отображения элементов. Адаптер преобразует каждый объект данных в ViewHolder и управляет созданием, заполнением и привязкой view-элементов.
    class UserAdapter(private val users: List<User>) : RecyclerView.Adapter<UserAdapter.ViewHolder>() {
        // ... методы onCreateViewHolder, onBindViewHolder, getItemCount
        // Здесь происходит адаптация данных User к ViewHolder для RecyclerView
    }
    
  • Работа с различными API и библиотеками: Если вы используете, например, две библиотеки для работы с изображениями, у которых разные методы загрузки (load(url) и fetch(imageUrl)), вы можете создать адаптер для унификации их использования в вашем коде.
  • Интеграция с legacy-модулями или старыми версиями SDK: Когда необходимо использовать функциональность из старой части проекта в новой архитектуре (например, Clean Architecture или MVP/MVVM).

Преимущества и недостатки

Преимущества:

  • Разделение ответственности: Клиентский код и адаптируемый код остаются независимыми и не знают друг о друге.
  • Гибкость и повторное использование: Позволяет использовать существующие классы в новых системах без изменения их исходного кода.
  • Соблюдение принципа Open/Closed: Система становится открытой для расширения (можно добавить новые адаптеры) и закрытой для изменения (не меняем клиент или адаптируемый объект).

Недостатки:

  • Увеличение сложности: Введение дополнительных классов может сделать код менее читаемым, если адаптеров становится слишком много.
  • Непрямой вызов (Overhead): Все запросы проходят через адаптер, что может добавить минимальную производительную нагрузку (в большинстве случаев это некритично).

Итог

Паттерн Адаптер — это мощный и элегантный инструмент для решения проблемы интеграции компонентов с различными контрактами (интерфейсами). Он широко применяется не только в теории, но и в реальной практике Android разработки, особенно при построении UI (RecyclerView) и работе с внешними зависимостями. Его понимание и правильное использование способствует созданию более гибкого, поддерживаемого и масштабируемого кода.