← Назад к вопросам

Какие паттерны проектирования вы знаете? Расскажите о двух, которые используете в работе.

2.0 Middle🔥 221 комментариев
#SOLID и паттерны проектирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

На протяжении карьеры я работал с множеством паттернов проектирования. Вот полный список, которые я знаю и применяю.

Все известные мне паттерны

Порождающие паттерны (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

Эти паттерны делают код более гибким, поддерживаемым и расширяемым.