Menu
Coddy logo textTech

Введение в паттерны проектирования

Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy — урок 85 из 107.

Паттерны проектирования — это многократно используемые решения распространенных проблем, возникающих при проектировании программного обеспечения. Это не код, который вы копируете напрямую, а скорее шаблоны, определяющие структуру ваших типов и их взаимодействие для решения конкретных задач.

Паттерны проектирования обычно делятся на три категории:

КатегорияНазначениеПримеры
ПорождающиеМеханизмы создания объектовSingleton, Factory, Builder
СтруктурныеКомпоновка типов в более крупные структурыAdapter, Decorator, Composite
ПоведенческиеВзаимодействие между объектамиObserver, Strategy, Command

В Go паттерны проектирования выглядят иначе, чем в традиционных ООП-языках.

Без классов или наследования Go реализует паттерны, используя интерфейсы, встраивание структур и композицию. Например, там, где Java могла бы использовать абстрактный класс, Go использует интерфейс. Там, где C++ мог бы использовать наследование, Go использует встраивание.

Изучение паттернов помогает вам распознавать распространенные проблемы и эффективно обсуждать решения с другими разработчиками. Когда кто-то упоминает «используйте здесь паттерн Strategy», вся команда понимает подход без долгих объяснений.

В следующих уроках вы реализуете несколько фундаментальных паттернов на Go, начиная с порождающих паттернов, таких как Singleton и Factory, а затем перейдете к поведенческим паттернам, таким как Observer и Strategy.

challenge icon

Задание

Легко

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

Вы организуете свой код в трех файлах:

  • notifier.go: Определите основной интерфейс и типы для вашей системы уведомлений.

    Создайте интерфейс Notifier с единственным методом Send(message string) string, который возвращает строку с подтверждением.

    Реализуйте два конкретных типа уведомлений:

    • EmailNotifier с полем Address — его метод Send возвращает Email to [address]: [message]
    • SMSNotifier с полем PhoneNumber — его метод Send возвращает SMS to [phone]: [message]
  • dispatcher.go: Создайте диспетчер, который работает с любым уведомлением через интерфейс.

    Создайте структуру NotificationDispatcher, которая содержит срез (slice) интерфейсов Notifier. Добавьте следующие методы:

    • AddNotifier(n Notifier) для регистрации уведомления
    • Broadcast(message string) []string, который отправляет сообщение через все зарегистрированные уведомления и возвращает срез всех строк с подтверждением

    Также создайте конструктор NewNotificationDispatcher(), который возвращает инициализированный диспетчер.

  • main.go: Настройте уведомления и разошлите сообщения.

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

    Затем прочитайте сообщение для рассылки. Отправьте его через все уведомления и выведите каждое подтверждение на новой строке.

Будут предоставлены следующие входные данные:

  • Строка 1: Количество уведомлений
  • Для каждого уведомления: тип (email или sms), затем место назначения
  • Последняя строка: Сообщение для рассылки

Например, для входных данных:

3
email
alice@example.com
sms
555-1234
email
bob@example.com
Server maintenance at midnight

Ваш вывод должен быть:

Email to alice@example.com: Server maintenance at midnight
SMS to 555-1234: Server maintenance at midnight
Email to bob@example.com: Server maintenance at midnight

И для входных данных:

2
sms
555-9999
sms
555-0000
Meeting canceled

Ваш вывод должен быть:

SMS to 555-9999: Meeting canceled
SMS to 555-0000: Meeting canceled

Эта структура демонстрирует, как интерфейсы обеспечивают гибкость и расширяемость дизайна. Диспетчер ничего не знает о конкретных типах уведомлений — он только знает, что они могут выполнять метод Send. Это фундамент, на котором строятся такие паттерны, как Наблюдатель и Стратегия!

Шпаргалка

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

Паттерны проектирования делятся на три категории:

КатегорияНазначениеПримеры
Порождающие (Creational)Механизмы создания объектовSingleton, Factory, Builder
Структурные (Structural)Компоновка типов в более крупные структурыAdapter, Decorator, Composite
Поведенческие (Behavioral)Взаимодействие между объектамиObserver, Strategy, Command

В Go паттерны проектирования реализуются с использованием интерфейсов, встраивания структур (struct embedding) и композиции вместо классов и наследования. Там, где традиционные ООП-языки используют абстрактные классы, Go использует интерфейсы. Там, где они используют наследование, Go использует встраивание.

Попробуйте сами

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Прочитать количество уведомлений
	countStr, _ := reader.ReadString('\n')
	count, _ := strconv.Atoi(strings.TrimSpace(countStr))

	// Создать новый диспетчер
	dispatcher := NewNotificationDispatcher()

	// Прочитать каждый уведомитель и добавить в диспетчер
	for i := 0; i < count; i++ {
		notifierType, _ := reader.ReadString('\n')
		notifierType = strings.TrimSpace(notifierType)

		destination, _ := reader.ReadString('\n')
		destination = strings.TrimSpace(destination)

		// TODO: Создать соответствующий уведомитель на основе типа
		// и добавить его в диспетчер
		// Подсказка: Проверьте, является ли notifierType "email" или "sms"

	}

	// Прочитать сообщение для рассылки
	message, _ := reader.ReadString('\n')
	message = strings.TrimSpace(message)

	// TODO: Разослать сообщение и вывести каждое подтверждение

}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

13Паттерны проектирования. Часть 1

Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн Abstract FactoryПаттерн ObserverПаттерн Strategy