Ответ
В своей практике я чаще всего применяю следующие паттерны, разделяя их по целям:
Порождающие (Creational):
- Фабричный метод (Factory Method) / Абстрактная фабрика (Abstract Factory): Использовал для создания семейств связанных объектов, например, различных провайдеров аутентификации (OAuth, JWT, LDAP) или парсеров разных форматов логов (JSON, XML, CSV). Это позволяет изолировать логику создания.
- Строитель (Builder): Применял для пошагового конструирования сложных объектов конфигурации или DTO с множеством необязательных полей, что делает код чище, чем вызов конструктора с десятком параметров.
- Внедрение зависимостей (Dependency Injection): Основа большинства современных фреймворков. Активно использую для повышения тестируемости и уменьшения связности компонентов.
Структурные (Structural):
- Адаптер (Adapter): Интегрировал сторонние библиотеки или legacy-код, создавая класс-обертку с нужным интерфейсом.
- Декоратор (Decorator): Использовал для динамического добавления функциональности, например, добавления логирования, кэширования или проверки прав доступа к основному сервису без изменения его кода.
- Фасад (Facade): Создавал упрощенные интерфейсы для работы со сложными подсистемами (например, модулем отчетности или интеграцией с внешним API).
Поведенческие (Behavioral):
- Стратегия (Strategy): Применял для инкапсуляции алгоритмов, которые могут меняться (например, алгоритмы сортировки, стратегии расчета скидок или способы отправки уведомлений — email, SMS, push). Это позволяет легко подменять их в runtime.
- Наблюдатель (Observer): Реализовывал для построения систем событий (event-driven). Например, при изменении статуса заказа автоматически запускались обработчики для отправки уведомления клиенту, обновления склада и логирования.
- Команда (Command): Использовал для инкапсуляции запросов как объектов, что полезно для реализации очереди задач, отмены операций (undo/redo) или отложенного выполнения.
Пример Стратегии на Java для валидации:
// Интерфейс стратегии
interface ValidationStrategy {
boolean execute(String data);
}
// Конкретные стратегии
class EmailValidation implements ValidationStrategy {
public boolean execute(String data) {
return data.matches("^[^@]+@[^@]+\.[^@]+$");
}
}
class PhoneValidation implements ValidationStrategy {
public boolean execute(String data) {
return data.matches("^\+?[0-9]{10,}$");
}
}
// Контекст, использующий стратегию
class Validator {
private ValidationStrategy strategy;
public Validator(ValidationStrategy strategy) {
this.strategy = strategy;
}
public boolean validate(String input) {
return strategy.execute(input);
}
}
// Использование
Validator emailValidator = new Validator(new EmailValidation());
boolean isValid = emailValidator.validate("test@example.com");
Ключевой принцип — не использовать паттерны ради самих паттернов, а применять их для решения конкретных проблем проектирования, таких как снижение связанности, повышение гибкости или улучшение тестируемости кода.
Ответ 18+ 🔞
Слушай, я тут подумал, про паттерны эти ваши. Ну, в работе-то они реально нужны, не просто так их придумали, ёпта. Расскажу, как я их юзаю, чтобы не было этой пиздопроебибны в коде.
Порождающие (Creational):
- Фабричный метод / Абстрактная фабрика: Вот, например, когда у тебя куча разных способов залогиниться — через OAuth, через JWT, ещё какую-то хуйню. Так вот, вместо того чтобы везде
if-elseгородить, ты эту логику создания в отдельное место засовываешь. Получается чисто, и когда новый способ добавишь — овердохуища кода переписывать не надо. - Строитель (Builder): А это вообще спасение, когда объект собирать надо из кучи полей, половина из которых необязательные. Представь конструктор с десятью параметрами — это же пиздец, в глазах рябит. А так — по кирпичику, красиво. Сам от себя охуевал, когда раньше без него делал.
- Внедрение зависимостей (Dependency Injection): Ну это основа основ, без этого сейчас нихуя не работает. Всё ради тестов, чувак. Чтобы не приклеено было намертво, а можно было подсунуть заглушку и проверить.
Структурные (Structural):
- Адаптер (Adapter): Бывает, подключаешь какую-нибудь старую библиотеку, написанную, будто на дворе 2002-й год. Интерфейс у неё — манда с ушами. Вот тут и пишешь обёрточку, которая твой красивый код с этим уродцем подруживает. Спасение, блядь.
- Декоратор (Decorator): О, это мощно. Допустим, есть у тебя сервис, который данные отдаёт. А потом понадобилось логирование добавить, потом кэширование. Так вот, вместо того чтобы в этот сервис лезть и всё там ломать, ты просто оборачиваешь его в декораторы. Как матрёшка. Добавил функциональность, а основной код даже не чихнул.
- Фасад (Facade): Это когда внутри система — ёперный театр, куча классов, всё громоздкое. А снаружи ты делаешь одну простую дверцу, через которую всё работает. Упрощение — наше всё, чтобы не ебать мозг себе и другим.
Поведенческие (Behavioral):
- Стратегия (Strategy): Один из любимых, серьёзно. Допустим, у тебя есть алгоритм, который может меняться. Скажем, способ расчёта скидки: для новых клиентов один, для постоянных — другой, ещё акция какая-то. Вместо кучи
switchилиif— ты каждый способ в отдельный класс засовываешь. И потом просто подменяешь одну стратегию на другую. Гибко, как хуй с горы. - Наблюдатель (Observer): Событийная модель, всё такое. Сделал что-то — разослал уведомления всем, кто подписан. Заказ оформили — клиенту письмо, складу сигнал, в лог запись. Все довольны, никто никого не дергает.
- Команда (Command): Это когда нужно действие в объект завернуть. Полезно для истории операций (чтоб откатить можно было), или для отложенного выполнения. Поставил команду в очередь — и пусть работает, когда сможет.
Вот, смотри, пример той самой Стратегии на Java, чтобы было понятнее, о чём речь:
// Интерфейс стратегии
interface ValidationStrategy {
boolean execute(String data);
}
// Конкретные стратегии
class EmailValidation implements ValidationStrategy {
public boolean execute(String data) {
return data.matches("^[^@]+@[^@]+\.[^@]+$");
}
}
class PhoneValidation implements ValidationStrategy {
public boolean execute(String data) {
return data.matches("^\+?[0-9]{10,}$");
}
}
// Контекст, использующий стратегию
class Validator {
private ValidationStrategy strategy;
public Validator(ValidationStrategy strategy) {
this.strategy = strategy;
}
public boolean validate(String input) {
return strategy.execute(input);
}
}
// Использование
Validator emailValidator = new Validator(new EmailValidation());
boolean isValid = emailValidator.validate("test@example.com");
Главное, чувак, — не становиться фанатиком. Не нужно впихивать паттерны куда ни попадя, лишь бы было. Это как молоток: если всё вокруг видишь гвоздем, то всё вокруг и будешь им долбить. Используй их, только когда реальная проблема есть: код связан сильнее, чем сиамские близнецы, или расширять его — терпения ноль ебать. Тогда да, тогда они выручают.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶