Паттерн Factory
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 87 из 107.
Паттерн Factory делегирует создание объектов отдельной функции или методу, позволяя создавать экземпляры без раскрытия логики создания. В отличие от Singleton, который контролирует количество экземпляров, Factory сосредоточен на гибком создании объектов на основе входных параметров.
В Go factory обычно представляет собой function, которая возвращает interface type, позволяя создавать разные конкретные типы через единый API:
type Notifier interface {
Send(message string) string
}
type EmailNotifier struct{}
type SMSNotifier struct{}
func (e EmailNotifier) Send(message string) string {
return "Email: " + message
}
func (s SMSNotifier) Send(message string) string {
return "SMS: " + message
}
func NewNotifier(notifierType string) Notifier {
switch notifierType {
case "email":
return EmailNotifier{}
case "sms":
return SMSNotifier{}
default:
return EmailNotifier{}
}
}Фабричная функция NewNotifier инкапсулирует решение о том, какой конкретный тип создать. Клиентский код работает только с интерфейсом Notifier, не зная о конкретной реализации:
notifier := NewNotifier("sms")
result := notifier.Send("Hello!") // "SMS: Hello!"Этот шаблон особенно полезен, когда вам нужно create объекты на основе условий времени выполнения, вы хотите централизовать сложную логику инициализации или вам нужно легко добавлять новые типы без изменения клиентского кода. Просто добавьте новую struct, реализующую interface, и обновите factory function.
Задание
ЛегкоДавайте создадим систему преобразования document с использованием паттерна Factory! Вы создадите factory, которая производит различные преобразователи document на основе целевого format, позволяя клиентскому коду работать с любым преобразователем через единый interface.
Вы организуете свой код в двух файлах:
converter.go: Define ваш interface converter и конкретные реализации.Create interface
Converterс methodConvert(content string) string, который принимает content document и возвращает преобразованный результат.Implement три типа converter:
PDFConverter: егоConvertmethod возвращаетPDF: [content]HTMLConverter: егоConvertmethod возвращаетHTML: <p>[content]</p>MarkdownConverter: егоConvertmethod возвращаетMD: # [content]
Create factory function
NewConverter(format string) Converter, которая возвращает соответствующий converter на основе строки format (pdf,htmlилиmarkdown). Для любого нераспознанного format вернитеPDFConverterкак значение default.main.go: Используйте свою factory для создания converter и обработки document.Read тип format и content document. Используйте factory для создания соответствующего converter, затем преобразуйте content и выведите result.
Будут предоставлены следующие входные данные:
- Строка 1: тип Format (
pdf,html,markdownили что-то ещё) - Строка 2: content document для преобразования
Например, если дано:
html
Welcome to Go ProgrammingВаш вывод должен быть таким:
HTML: <p>Welcome to Go Programming</p>А если дано:
markdown
Chapter OneВаш вывод должен быть таким:
MD: # Chapter OneА если дано:
pdf
Annual Report 2024Ваш вывод должен быть таким:
PDF: Annual Report 2024А если дано:
docx
Meeting NotesВаш вывод должен быть таким:
PDF: Meeting NotesОбратите внимание, что main-коду не нужно знать о конкретных типах converter. Он просто запрашивает converter у factory и использует interface. Благодаря этому позже легко добавлять новые format без изменения клиентского кода!
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Прочитать тип формата
scanner.Scan()
format := scanner.Text()
// Прочитать содержимое документа
scanner.Scan()
content := scanner.Text()
// TODO: Использовать фабрику для создания соответствующего конвертера
// TODO: Преобразовать содержимое и вывести результат
fmt.Println(result)
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП в Go
Внешние файлыРабочее пространство и модули GoПакеты и импортыЭкспортируемые и неэкспортируемые именаВведение в ООП в GoСтруктуры как классыОпределение методов структурПолучатели-указатели и получатели-значенияИнициализация структурФункции-конструкторыИтоги — Простой калькулятор4Интерфейсы
Введение в интерфейсыНеявная реализацияИнтерфейс как контрактПустой интерфейс (any)Утверждение типаПереключатель типовКомпозиция интерфейсовИнтерфейсы Stringer и ErrorПовторение: Калькулятор фигур7Инкапсуляция
Экспортируемые и неэкспортируемые поляИнкапсуляция на уровне пакетовГеттеры и сеттерыСокрытие информации в GoИтоги — Записи о студентах10Обобщения (Generics) (Go 1.18+)
Введение в GenericsПараметры типовОграничения типовОбобщенные структурыОбходной путь для обобщенных методовИтоги — Обобщенная коллекция13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн Abstract FactoryПаттерн ObserverПаттерн Strategy2Глубокое погружение в типы и структуры
Базовые и составные типыОпределение пользовательских типовТеги структурАнонимные структурыВложенные структурыНулевые значения и значения по умолчаниюПовторение — Контактная книга5Композиция вместо наследования
Почему в Go нет наследованияОсновы встраивания структурПродвижение методовВстраивание нескольких структурВстраивание против агрегацииЗатенение встроенных методовИтоги — Иерархия сотрудников8Обработка ошибок и ООП
Интерфейс errorПользовательские типы ошибокОбертывание ошибок (fmt.Errorf)Sentinel-ошибкиerrors.Is() и errors.As()Panic, Defer и RecoverИтоги — Парсер файлов11Стандартная библиотека и ООП
io.Reader и io.Writersort.InterfaceИнтерфейс fmt.Stringerencoding/json со структурамиИнтерфейс http.HandlerПовторение: модели REST API14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикMiddleware как Декоратор3Указатели и память
Основы указателей в GoУказатели на структурыПередача по значению и по ссылкеФункция new()Сборка мусора в GoПовторение: Конструктор связного списка6Полиморфизм в Go
Полиморфизм через интерфейсыУтиная типизация в GoПравила реализации интерфейсовПолиморфные коллекцииВнедрение зависимостейИтоги — Обработчик платежей9Конкурентность и ООП
Основы горутинКаналы и взаимодействиеБуферизованные и небуферизованные каналыОператор selectsync.Mutex и sync.RWMutexsync.WaitGroupПроектирование потокобезопасных структурПовторение — Worker PoolПотренируйтесь самостоятельно: Онлайн-компилятор Go