Какие паттерны проектирования вы знаете? Расскажите о двух, которые используете в работе.
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерны проектирования
На протяжении карьеры я работал с множеством паттернов проектирования. Вот полный список, которые я знаю и применяю.
Все известные мне паттерны
Порождающие паттерны (Creational):
- Singleton — единственный экземпляр класса
- Factory Method — создание объектов через методы
- Abstract Factory — семейства объектов
- Builder — построение сложных объектов
- Prototype — клонирование объектов
Структурные паттерны (Structural):
- Adapter — адаптация интерфейсов
- Bridge — разделение абстракции и реализации
- Composite — составные объекты
- Decorator — добавление функциональности
- Facade — упрощённый интерфейс
- Flyweight — разделение объектов
- Proxy — управление доступом
Поведенческие паттерны (Behavioral):
- Chain of Responsibility — цепь обработчиков
- Command — инкапсуляция команд
- Interpreter — интерпретация языков
- Iterator — обход элементов
- Mediator — посредник между объектами
- Memento — сохранение состояния
- Observer — наблюдатели
- State — переключение состояний
- Strategy — выбор алгоритма
- Template Method — шаблон алгоритма
- Visitor — посещение элементов
Паттерн 1: Dependency Injection (IoC Container)
Использую в 100% проектов с Spring Boot. Это архитектурный паттерн, основанный на инверсии управления.
Проблема без DI:
public class UserService {
private UserRepository repository = new UserRepositoryImpl(); // Hard dependency
private EmailService emailService = new EmailService();
public void registerUser(User user) {
// сложно тестировать, жёсткие зависимости
repository.save(user);
emailService.sendWelcomeEmail(user);
}
}
С Dependency Injection:
@Service
public class UserService {
private final UserRepository repository;
private final EmailService emailService;
// Spring автоматически инжектит зависимости
public UserService(UserRepository repository, EmailService emailService) {
this.repository = repository;
this.emailService = emailService;
}
public void registerUser(User user) {
repository.save(user);
emailService.sendWelcomeEmail(user);
}
}
Преимущества:
- Слабая связанность (loose coupling)
- Легко тестировать (mock dependencies)
- Гибкость конфигурации
- Управление жизненным циклом объектов
В тестах:
@Test
void testUserRegistration() {
UserRepository mockRepo = mock(UserRepository.class);
EmailService mockEmail = mock(EmailService.class);
UserService service = new UserService(mockRepo, mockEmail);
User user = new User("John", "john@example.com");
service.registerUser(user);
verify(mockRepo).save(user);
verify(mockEmail).sendWelcomeEmail(user);
}
Паттерн 2: Strategy
Активно применяю для выбора алгоритмов обработки платежей, валидации и бизнес-логики.
Сценарий: Система должна обрабатывать платежи разными способами (кредитная карта, PayPal, криптовалюта).
Без Strategy (плохо):
public class PaymentProcessor {
public void processPayment(String method, BigDecimal amount) {
if (method.equals("CARD")) {
// обработка карты
} else if (method.equals("PAYPAL")) {
// обработка PayPal
} else if (method.equals("CRYPTO")) {
// обработка крипто
}
// что-то забыл? сложно добавлять новые способы
}
}
С Strategy паттерном:
// Интерфейс стратегии
public interface PaymentStrategy {
PaymentResult process(BigDecimal amount, PaymentDetails details);
void refund(String transactionId, BigDecimal amount);
}
// Конкретные стратегии
@Component
public class CreditCardStrategy implements PaymentStrategy {
private final CreditCardGateway gateway;
public CreditCardStrategy(CreditCardGateway gateway) {
this.gateway = gateway;
}
@Override
public PaymentResult process(BigDecimal amount, PaymentDetails details) {
return gateway.charge(details.getCardNumber(), amount);
}
@Override
public void refund(String transactionId, BigDecimal amount) {
gateway.refund(transactionId, amount);
}
}
@Component
public class PayPalStrategy implements PaymentStrategy {
private final PayPalClient client;
public PayPalStrategy(PayPalClient client) {
this.client = client;
}
@Override
public PaymentResult process(BigDecimal amount, PaymentDetails details) {
return client.createPayment(details.getEmail(), amount);
}
@Override
public void refund(String transactionId, BigDecimal amount) {
client.refundPayment(transactionId);
}
}
// Контекст, который использует стратегию
@Service
public class PaymentService {
private final Map<PaymentMethod, PaymentStrategy> strategies;
public PaymentService(CreditCardStrategy cardStrategy, PayPalStrategy paypalStrategy) {
this.strategies = Map.of(
PaymentMethod.CARD, cardStrategy,
PaymentMethod.PAYPAL, paypalStrategy
);
}
public PaymentResult processPayment(
PaymentMethod method,
BigDecimal amount,
PaymentDetails details
) {
PaymentStrategy strategy = strategies.get(method);
if (strategy == null) {
throw new IllegalArgumentException("Unsupported payment method: " + method);
}
return strategy.process(amount, details);
}
public void refundPayment(PaymentMethod method, String transactionId, BigDecimal amount) {
PaymentStrategy strategy = strategies.get(method);
strategy.refund(transactionId, amount);
}
}
Преимущества Strategy:
- Лёгко добавлять новые способы платежа (новый класс + регистрация)
- Алгоритмы изолированы друг от друга
- Тестируются независимо
- Выбор алгоритма во время выполнения
Расширение (добавление новой стратегии):
@Component
public class CryptoStrategy implements PaymentStrategy {
private final BlockchainService blockchain;
public CryptoStrategy(BlockchainService blockchain) {
this.blockchain = blockchain;
}
@Override
public PaymentResult process(BigDecimal amount, PaymentDetails details) {
return blockchain.sendTransaction(details.getWalletAddress(), amount);
}
@Override
public void refund(String transactionId, BigDecimal amount) {
blockchain.reverseTransaction(transactionId);
}
}
// И просто добавляем в конструктор PaymentService
// Никаких изменений в остальном коде!
Где ещё применяю паттерны
- Decorator — логирование, трансакции (Spring AOP)
- Observer — event-driven архитектура (Spring Events)
- Factory — создание объектов в Spring
- Proxy — ленивая загрузка в Hibernate
- Template Method — BaseController в Spring MVC
- Chain of Responsibility — фильтры в Spring Security
Эти паттерны делают код более гибким, поддерживаемым и расширяемым.