История двух интерфейсов

Введение

Добро пожаловать, энтузиасты кодирования! Давайте отправимся в захватывающее путешествие, чтобы разгадать тайны шаблона проектирования адаптера, особенно в контексте Go. Представьте себе: вы увлеченный турист в чужой стране, батарея вашего телефона разряжена на 1%, и как только вы вытаскиваете зарядное устройство, вы понимаете — о-о — оно не подходит для местных розеток. Было бы лучше иметь дорожный адаптер — удобное маленькое устройство, которое соединяет зарядное устройство и внешнюю розетку.

При разработке программного обеспечения мы часто сталкиваемся с похожими проблемами. У нас могут быть компоненты или интерфейсы, которые не «подходят» друг другу напрямую. Не бойтесь, потому что в таких ситуациях мы можем использовать адаптер (так же, как этот адаптер для путешествий) для решения этих проблем совместимости. В этом суть паттерна адаптера, который мы сегодня рассмотрим в программировании на Go.

Теперь, когда мы заинтересовали вас, давайте продолжим и разберемся с шаблоном адаптера в Go.

Простое пошаговое руководство по шаблону адаптера в Go

Шаг 1: Определите свои интерфейсы

Представьте, что у нас есть интерфейс MediaPlayer с методом Play...

type MediaPlayer interface {
    Play(audioType string, fileName string) error
}

…и мы хотим представить новый, более шикарный AdvancedMediaPlayer, который может воспроизводить как аудио-, так и видеофайлы.

type AdvancedMediaPlayer interface {
    PlayVideo(fileName string) error
    PlayAudio(fileName string) error
}

Шаг 2: Реализуйте AdvancedMediaPlayer

Для AdvancedMediaPlayer мы создаем VLCPlayer. Это модное новое устройство, которое мы не можем подключить напрямую к нашей старой системе.

type VLCPlayer struct{}

func (v *VLCPlayer) PlayVideo(fileName string) error {
    fmt.Printf("Playing video file. Name: %s\n", fileName)
    return nil
}

func (v *VLCPlayer) PlayAudio(fileName string) error {
    fmt.Printf("Playing audio file. Name: %s\n", fileName)
    return nil
}

Шаг 3: Создайте адаптер

Точно так же, как дорожный адаптер, мы теперь делаем MediaAdapter. Он реализует интерфейс MediaPlayer, но внутри использует интерфейс AdvancedMediaPlayer.

type MediaAdapter struct {
    advancedMusicPlayer AdvancedMediaPlayer
}

func (m *MediaAdapter) Play(audioType string, fileName string) error {
    if audioType == "vlc" {
        return m.advancedMusicPlayer.PlayVideo(fileName)
    } else if audioType == "mp4" {
        return m.advancedMusicPlayer.PlayAudio(fileName)
    }
    return fmt.Errorf("invalid media. %s format not supported", audioType)
}

Шаг 4: Интеграция всего

Наконец, давайте свяжем все вместе с нашим AudioPlayer, который также реализует интерфейс MediaPlayer. Он будет использовать наш MediaAdapter для обработки новых типов мультимедиа.

type AudioPlayer struct {
    mediaAdapter MediaPlayer
}

func (a *AudioPlayer) Play(audioType string, fileName string) error {
    // Inbuilt support for mp3 music files
    if audioType == "mp3" {
        fmt.Printf("Playing mp3 file. Name: %s\n", fileName)
        return nil
    }

    // MediaAdapter is providing support for other file formats
    else if audioType == "vlc" || audioType == "mp4" {
        a.mediaAdapter = &MediaAdapter{&VLCPlayer{}}
        return a.mediaAdapter.Play(audioType, fileName)
    }

    return fmt.Errorf("invalid media. %s format not supported", audioType)
}

Последние мысли

И вот оно! Используя шаблон адаптера, мы интегрировали наш новый VLCPlayer в нашу систему без каких-либо проблем. Когда вы сталкиваетесь с несовместимыми интерфейсами, помните о дорожном адаптере и используйте шаблон адаптера. Речь идет о том, чтобы все работало гладко, несмотря на различия. До следующего раза, кодируйте и адаптируйтесь с апломбом!