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

Ответ

Adapter – структурный паттерн, позволяющий несовместимым интерфейсам работать вместе.

Пример:

// Интерфейс, который ожидает клиент
interface MediaPlayer {
    fun play(audioType: String, fileName: String)
}

// Адаптируемый класс с другим интерфейсом
class AdvancedMediaPlayer {
    fun playVlc(fileName: String) = println("Playing VLC: $fileName")
    fun playMp4(fileName: String) = println("Playing MP4: $fileName")
}

// Адаптер
class MediaAdapter(private val advancedPlayer: AdvancedMediaPlayer) : MediaPlayer {
    override fun play(audioType: String, fileName: String) {
        when (audioType.lowercase()) {
            "vlc" -> advancedPlayer.playVlc(fileName)
            "mp4" -> advancedPlayer.playMp4(fileName)
            else -> throw UnsupportedOperationException("Unsupported format: $audioType")
        }
    }
}

// Использование
val player: MediaPlayer = MediaAdapter(AdvancedMediaPlayer())
player.play("mp4", "movie.mp4") // Playing MP4: movie.mp4

Суть: Адаптер преобразует вызовы одного интерфейса в другой, сохраняя функциональность.

Ответ 18+ 🔞

Ну смотри, представь себе такую хуйню. У тебя есть, допустим, какой-нибудь старый проигрыватель, который только винил крутит. А ты ему суёшь флешку с MP3. Он её, естественно, не жрёт, смотрит на тебя как баран на новые ворота. Вот тут-то и нужен адаптер, этакая переходная хуйня, которая скажет этому древнему девайсу: «Э, сабака сука, не тупи, вот тебе сигнал, как будто с пластинки, а на самом деле я его из цифры выковырял».

Вот и в коде та же история. Есть у тебя класс AdvancedMediaPlayer — навороченная мартышлюшка, которая и VLC, и MP4 проигрывает. Но интерфейс у него свой, особенный. А твой основной код, клиент, общается только через интерфейс MediaPlayer, у которого метод play(audioType, fileName). И они друг друга не понимают, как два барана на мосту.

И что делать? Правильно, сделать посредника — адаптер. Это как переводчик между твоим упрямым дедом, который говорит только на деревенском диалекте, и продавцом в магазине техники. Адаптер (MediaAdapter) реализует тот интерфейс, который ждёт клиент (то есть у него есть метод play), но внутри он не сам всё делает, а дергает за ниточки того самого навороченного плеера.

Смотри на код:

class MediaAdapter(private val advancedPlayer: AdvancedMediaPlayer) : MediaPlayer {
    override fun play(audioType: String, fileName: String) {
        when (audioType.lowercase()) {
            "vlc" -> advancedPlayer.playVlc(fileName)
            "mp4" -> advancedPlayer.playMp4(fileName)
            else -> throw UnsupportedOperationException("Unsupported format: $audioType")
        }
    }
}

Вот видишь? Клиент кричит: «Эй, адаптер, включи мне movie.mp4!». Адаптер такой: «Да похуй, ща сделаем». Берёт этого зазнавшегося AdvancedMediaPlayer и говорит ему: «Слушай сюда, умник, держи файл и включай его своим методом playMp4, а клиенту отчитайся как будто от меня». И всё работает! Клиент доволен, он общается через знакомый интерфейс. Продвинутый плеер тоже доволен, его не заставляют менять свои привычные методы playVlc и playMp4. А адаптер — герой, невидимый гвоздь программы, который всё скрепил.

Суть-то какая? Адаптер — это такой хитрожопый паттерн, который подменяет один интерфейс на другой, не ломая при этом всю существующую логику. Он как переходник с евровилки на советскую розетку. Без него — нихуя не работает, а с ним — пожалуйста, ебать-копать, всё шуршит. Главное, чтобы контакты не искрили, а то будет вам не хиросима, а настоящий пиздец в продакшене.