Паттерн «Адаптер»
Паттерн «Адаптер» действует как мост между двумя несовместимыми интерфейсами и является структурным паттерном проектирования. Через посредника (адаптер) он преобразует интерфейс одного класса в другой интерфейс, ожидаемый клиентом, позволяя классам, которые изначально не могли работать вместе, взаимодействовать.
Этот паттерн включает один класс, который отвечает за объединение функциональности независимых или несовместимых интерфейсов. Реальный пример — устройство для чтения карт, которое действует как адаптер между картой памяти и ноутбуком. Вы вставляете карту памяти в устройство для чтения карт, затем вставляете устройство для чтения карт в ноутбук, чтобы карту памяти можно было прочитать через ноутбук.
Предположим, есть аудиоплеер, который может воспроизводить только файлы MP3. Теперь нам нужно воспроизводить файлы VLC и MP4. Это можно сделать, создав адаптер:
- Целевой интерфейс: Определите интерфейс аудиоплеера, который может воспроизводить файлы в нескольких форматах.
- Адаптируемый класс: Существующий аудиоплеер может воспроизводить только файлы MP3.
- Класс адаптера: Создайте новый класс, который реализует целевой интерфейс, внутренне использует адаптируемый класс для воспроизведения файлов MP3 и добавляет поддержку файлов VLC и MP4.
Обзор
Паттерн «Адаптер» — это паттерн проектирования программного обеспечения, предназначенный для решения проблем совместимости между различными интерфейсами.
Назначение: Преобразовать интерфейс одного класса в другой интерфейс, чтобы изначально несовместимые классы могли работать вместе.
Основные решаемые проблемы: В программной системе необходимо поместить существующий объект в новую среду, но интерфейс, требуемый новой средой, не соответствует существующему объекту.
Сценарий использования
- Требуется использовать существующий класс, но его интерфейс не соответствует требованиям системы.
- Желание создать повторно используемый класс, который работает с несколькими несвязанными классами (включая классы, которые могут быть добавлены в будущем), возможно, не имеющими единого интерфейса.
- Посредством преобразования интерфейса интегрировать один класс в другую систему классов.
Подход к реализации
- Наследование или зависимость: Рекомендуется использовать зависимость, а не наследование, чтобы сохранить гибкость.
Ключевой код
Адаптер наследует от существующего объекта или зависит от него и реализует требуемый целевой интерфейс.
Пример приложения
- Адаптер напряжения: Преобразовать напряжение 110V в 220V для адаптации к электрическим стандартам разных стран.
- Преобразование интерфейса: Например, преобразование интерфейса Enumeration из Java JDK 1.1 в интерфейс Iterator из 1.2.
- Кроссплатформенная работа: Запуск программ Windows в Linux.
- Подключение к базе данных: В Java JDBC взаимодействует с разными типами баз данных через паттерн «Адаптер».
Преимущества
- Способствует взаимодействию между классами, даже если они не имеют прямой связи.
- Повышает повторное использование.
- Повышает прозрачность класса.
- Обеспечивает хорошую гибкость.
Недостатки
- Чрезмерное использование паттерна Адаптер может привести к хаотичной структуре системы, которую трудно понять и поддерживать.
- В Java, поскольку можно наследовать только один класс, можно адаптировать только один класс, и целевой класс должен быть абстрактным.
Рекомендации по использованию
- Паттерн Адаптер следует использовать с осторожностью, особенно на этапе детального проектирования; в основном он применяется для решения проблем в существующих системах.
- Паттерн Адаптер — подходящий выбор, когда рассматривается изменение интерфейса нормально работающей системы.
Таким образом, паттерн Адаптер может ясно выразить свои основные концепции и применения, избегая ненужной сложности.
Структура
Паттерн Адаптер содержит следующие основные роли:
- Целевой интерфейс (Target): Определяет интерфейс, необходимый клиенту.
- Адаптируемый класс (Adaptee): Определяет уже существующий интерфейс, который нужно адаптировать.
- Класс адаптера (Adapter): Реализует целевой интерфейс и вызывает методы класса Adaptee через композицию или наследование, тем самым реализуя целевой интерфейс.
Реализация
У нас естьMediaPlayerинтерфейс и реализацияMediaPlayerкласс сущности интерфейсаAudioPlayer. По умолчанию,AudioPlayerможет воспроизводить аудиофайлы в формате mp3.
У нас также есть другой интерфейсAdvancedMediaPlayerи реализуетAdvancedMediaPlayerКонкретный класс реализации этого интерфейса. Этот класс может воспроизводить файлы в форматах vlc и mp4.
Мы хотим заставитьAudioPlayerвоспроизводить аудиофайлы в других форматах. Чтобы реализовать эту функциональность, нам нужно создать класс, реализующий...MediaPlayerкласс-адаптер интерфейсаMediaAdapter, и используетAdvancedMediaPlayerобъект для воспроизведения требуемого формата.
AudioPlayerИспользует класс-адаптерMediaAdapterПередаёт требуемый тип аудио; нет необходимости знать фактический класс, который может воспроизводить аудио в требуемом формате.AdapterPatternDemoИспользование классаAudioPlayerКласс для воспроизведения различных форматов.
Шаг 1
Создайте интерфейсы для медиаплеера и более продвинутого медиаплеера.
MediaPlayer.java
AdvancedMediaPlayer.java
Шаг 2
Создайте реализациюAdvancedMediaPlayerКласс сущности интерфейса.
VlcPlayer.java
Mp4Player.java
Шаг 3
Создайте реализациюMediaPlayerкласса адаптера для интерфейса.
MediaAdapter.java
Шаг 4
Создайте реализациюMediaPlayerкласс сущности интерфейса.
AudioPlayer.java
Шаг 5
Используйте AudioPlayer для воспроизведения различных типов аудиоформатов.
AdapterPatternDemo.java
Шаг 6
Запустите программу, выведите результаты:
Playing mp3 file. Name: beyond the horizon.mp3 Playing mp4 file. Name: alone.mp4 Playing vlc file. Name: far far away.vlc Invalid media. avi format not supportedДругие расширения