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

Какие паттерны проектирования реализовывал

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

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

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

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

Паттерны проектирования: Практический опыт

Введение

Паттерны проектирования - это проверенные решения для повторяющихся проблем в архитектуре и дизайне кода. Я использую их ежедневно в своих проектах.

Порождающие паттерны (Creational)

1. Singleton Pattern

Описание: гарантирует, что класс имеет только один экземпляр.

// Ленивая инициализация (double-checked locking)
public class DatabaseConnection {
    private static volatile DatabaseConnection instance;
    
    private DatabaseConnection() {}
    
    public static DatabaseConnection getInstance() {
        if (instance == null) {
            synchronized (DatabaseConnection.class) {
                if (instance == null) {
                    instance = new DatabaseConnection();
                }
            }
        }
        return instance;
    }
}

// В Spring (проще):
@Component
public class DatabaseConnection {
    // Spring автоматически создаёт singleton bean
}

Когда использовал: конфигурация БД, логирование, cache manager.

2. Factory Pattern

Описание: создание объектов без указания точных классов.

// Abstract Factory
public abstract class PaymentProcessor {
    public abstract void process(BigDecimal amount);
}

public class CreditCardProcessor extends PaymentProcessor {
    @Override
    public void process(BigDecimal amount) {
        System.out.println("Processing credit card: " + amount);
    }
}

public class PayPalProcessor extends PaymentProcessor {
    @Override
    public void process(BigDecimal amount) {
        System.out.println("Processing PayPal: " + amount);
    }
}

// Factory
public class PaymentProcessorFactory {
    public static PaymentProcessor create(PaymentMethod method) {
        return switch (method) {
            case CREDIT_CARD -> new CreditCardProcessor();
            case PAYPAL -> new PayPalProcessor();
            default -> throw new IllegalArgumentException();
        };
    }
}

// Использование
PaymentProcessor processor = PaymentProcessorFactory.create(PaymentMethod.CREDIT_CARD);
processor.process(BigDecimal.valueOf(99.99));

Когда использовал: создание платежных обработчиков, различные реализации сервисов.

3. Builder Pattern

Описание: пошаговое построение сложного объекта.

// Query builder
public class QueryBuilder {
    private String select;
    private String from;
    private String where;
    private String orderBy;
    
    public QueryBuilder select(String columns) {
        this.select = "SELECT " + columns;
        return this;
    }
    
    public QueryBuilder from(String table) {
        this.from = "FROM " + table;
        return this;
    }
    
    public QueryBuilder where(String condition) {
        this.where = "WHERE " + condition;
        return this;
    }
    
    public QueryBuilder orderBy(String columns) {
        this.orderBy = "ORDER BY " + columns;
        return this;
    }
    
    public String build() {
        return String.join(" ", select, from, where, orderBy).replaceAll(" +", " ").trim();
    }
}

// Использование
String query = new QueryBuilder()
    .select("id, name, email")
    .from("users")
    .where("age > 18")
    .orderBy("name")
    .build();

// SELECT id, name, email FROM users WHERE age > 18 ORDER BY name

// Реальный пример: Hibernate Criteria API
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> root = query.from(User.class);
query.select(root)
    .where(cb.greaterThan(root.get("age"), 18))
    .orderBy(cb.asc(root.get("name")));

Когда использовал: построение запросов, конфигурация объектов, HTTP запросы.

Структурные паттерны (Structural)

4. Adapter Pattern

Описание: преобразование интерфейса объекта в другой интерфейс.

// Старая система (legacy)
public interface LegacyUserService {
    User getUserById(int id);
}

// Новая система ожидает
public interface ModernUserService {
    User findUserById(Long userId);
}

// Adapter
public class UserServiceAdapter implements ModernUserService {
    private final LegacyUserService legacyService;
    
    public UserServiceAdapter(LegacyUserService legacyService) {
        this.legacyService = legacyService;
    }
    
    @Override
    public User findUserById(Long userId) {
        return legacyService.getUserById(userId.intValue());
    }
}

// Использование
ModernUserService service = new UserServiceAdapter(new LegacyUserServiceImpl());
User user = service.findUserById(123L);

Когда использовал: интеграция с legacy системами, использование сторонних библиотек.

5. Decorator Pattern

Описание: добавление новых функций объекту без изменения его структуры.

// Base interface
public interface DataSource {
    String getData();
}

// Основная реализация
public class SimpleDataSource implements DataSource {
    @Override
    public String getData() {
        return "Raw data";
    }
}

// Decorator 1: Compression
public class CompressionDecorator implements DataSource {
    private final DataSource dataSource;
    
    public CompressionDecorator(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    @Override
    public String getData() {
        return compress(dataSource.getData());
    }
    
    private String compress(String data) {
        return "[COMPRESSED] " + data;
    }
}

// Decorator 2: Encryption
public class EncryptionDecorator implements DataSource {
    private final DataSource dataSource;
    
    public EncryptionDecorator(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    @Override
    public String getData() {
        return encrypt(dataSource.getData());
    }
    
    private String encrypt(String data) {
        return "[ENCRYPTED] " + data;
    }
}

// Использование (chaining)
DataSource source = new SimpleDataSource();
source = new CompressionDecorator(source);
source = new EncryptionDecorator(source);

String data = source.getData();
// [ENCRYPTED] [COMPRESSED] Raw data

Когда использовал: логирование (логирование + компрессия + шифрование), stream обработка.

6. Proxy Pattern

Описание: контроль доступа к другому объекту.

// Subject interface
public interface UserService {
    User getUser(Long id);
}

// Real subject
public class UserServiceImpl implements UserService {
    @Override
    public User getUser(Long id) {
        // Дорогостоящая операция
        return databaseQuery(id);
    }
}

// Proxy с кэшированием
public class CachedUserServiceProxy implements UserService {
    private final UserService userService;
    private final Map<Long, User> cache = new HashMap<>();
    
    public CachedUserServiceProxy(UserService userService) {
        this.userService = userService;
    }
    
    @Override
    public User getUser(Long id) {
        return cache.computeIfAbsent(id, key -> userService.getUser(key));
    }
}

// В Spring (AOP proxy)
@Service
public class UserService {
    @Cacheable("users")
    public User getUser(Long id) {
        return userRepository.findById(id).orElseThrow();
    }
}

Когда использовал: кэширование (Spring @Cacheable), логирование доступа, ленивая загрузка.

Поведенческие паттерны (Behavioral)

7. Observer Pattern

Описание: один объект уведомляет множество других об изменениях.

// Event system
public class OrderCreatedEvent {
    private final Long orderId;
    private final BigDecimal amount;
    
    public OrderCreatedEvent(Long orderId, BigDecimal amount) {
        this.orderId = orderId;
        this.amount = amount;
    }
}

// Observer 1
@Component
public class EmailNotificationService {
    @EventListener
    public void onOrderCreated(OrderCreatedEvent event) {
        System.out.println("Sending email for order: " + event.getOrderId());
    }
}

// Observer 2
@Component
public class InventoryService {
    @EventListener
    public void onOrderCreated(OrderCreatedEvent event) {
        System.out.println("Updating inventory for order: " + event.getOrderId());
    }
}

// Publisher
@Service
public class OrderService {
    private final ApplicationEventPublisher eventPublisher;
    
    public void createOrder(Order order) {
        orderRepository.save(order);
        eventPublisher.publishEvent(new OrderCreatedEvent(order.getId(), order.getAmount()));
    }
}

Когда использовал: event-driven архитектура, уведомления, асинхронная обработка.

8. Strategy Pattern

Описание: определение семейства алгоритмов и выбор нужного во время выполнения.

// Strategy interface
public interface SortingStrategy {
    <T extends Comparable<T>> List<T> sort(List<T> items);
}

// Concrete strategies
public class QuickSort implements SortingStrategy {
    @Override
    public <T extends Comparable<T>> List<T> sort(List<T> items) {
        // QuickSort implementation
        return items;
    }
}

public class MergeSort implements SortingStrategy {
    @Override
    public <T extends Comparable<T>> List<T> sort(List<T> items) {
        // MergeSort implementation
        return items;
    }
}

// Context
public class Sorter {
    private final SortingStrategy strategy;
    
    public Sorter(SortingStrategy strategy) {
        this.strategy = strategy;
    }
    
    public <T extends Comparable<T>> List<T> sort(List<T> items) {
        return strategy.sort(items);
    }
}

// Использование
Sorter sorter = new Sorter(new QuickSort());
List<Integer> sorted = sorter.sort(Arrays.asList(3, 1, 4, 1, 5));

Когда использовал: различные алгоритмы поиска, фильтрации, расчётов (tax calculation, shipping, discounts).

9. Command Pattern

Описание: инкапсулирование запроса как объекта.

// Command interface
public interface Command {
    void execute();
    void undo();
}

// Concrete commands
public class TransferMoneyCommand implements Command {
    private final Account from;
    private final Account to;
    private final BigDecimal amount;
    
    public TransferMoneyCommand(Account from, Account to, BigDecimal amount) {
        this.from = from;
        this.to = to;
        this.amount = amount;
    }
    
    @Override
    public void execute() {
        from.withdraw(amount);
        to.deposit(amount);
    }
    
    @Override
    public void undo() {
        to.withdraw(amount);
        from.deposit(amount);
    }
}

// Invoker
public class TransactionManager {
    private final Stack<Command> history = new Stack<>();
    
    public void execute(Command command) {
        command.execute();
        history.push(command);
    }
    
    public void undo() {
        if (!history.isEmpty()) {
            history.pop().undo();
        }
    }
}

// Использование
TransactionManager manager = new TransactionManager();
Command transfer = new TransferMoneyCommand(accountA, accountB, amount);
manager.execute(transfer);  // Трансфер выполнен
manager.undo();  // Отмена

Когда использовал: системы с историей операций, undo/redo функционал, очереди задач.

10. Template Method Pattern

Описание: определение скелета алгоритма в базовом классе, оставляя детали для подклассов.

// Template
public abstract class DataProcessor {
    public final void process(String data) {
        data = validateData(data);
        data = transformData(data);
        storeData(data);
    }
    
    protected String validateData(String data) {
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("Data is empty");
        }
        return data;
    }
    
    protected abstract String transformData(String data);
    protected abstract void storeData(String data);
}

// Implementations
public class JsonProcessor extends DataProcessor {
    @Override
    protected String transformData(String data) {
        return "JSON: " + data;
    }
    
    @Override
    protected void storeData(String data) {
        System.out.println("Storing: " + data);
    }
}

// Использование
DataProcessor processor = new JsonProcessor();
processor.process("{\"key\": \"value\"}");

Когда использовал: обработка файлов, миграция данных, различные отчёты.

Архитектурные паттерны

11. MVC Pattern

Использую в: Spring MVC, веб-приложениях.

// Model
public class User {
    private Long id;
    private String name;
    private String email;
}

// Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return ResponseEntity.ok(user);
    }
}

// Service (Business Logic)
@Service
public class UserService {
    public User getUserById(Long id) {
        return userRepository.findById(id).orElseThrow();
    }
}

12. Repository Pattern

Описание: абстракция доступа к данным.

public interface UserRepository extends JpaRepository<User, Long> {
    User findByEmail(String email);
    List<User> findByAgeGreaterThan(int age);
}

@Service
public class UserService {
    private final UserRepository repository;
    
    public User findUser(String email) {
        return repository.findByEmail(email);
    }
}

13. Dependency Injection

Использую в: Spring Framework (автоматически).

@Service
public class UserService {
    private final UserRepository repository;
    private final EmailService emailService;
    
    // Constructor injection (лучше всего)
    public UserService(UserRepository repository, EmailService emailService) {
        this.repository = repository;
        this.emailService = emailService;
    }
}

Паттерны высоконагруженных систем

14. Circuit Breaker

Описание: защита от cascading failures.

@Service
public class OrderService {
    @CircuitBreaker(name = "paymentService", fallbackMethod = "fallback")
    public void processPayment(Order order) {
        paymentService.charge(order.getAmount());
    }
    
    private void fallback(Order order, Exception e) {
        order.setStatus("PENDING_PAYMENT");
        orderRepository.save(order);
    }
}

15. Caching Pattern

@Service
public class ProductService {
    @Cacheable("products")
    public Product getProduct(Long id) {
        return productRepository.findById(id).orElseThrow();
    }
}

Заключение

Паттерны, которые использую чаще всего:

  1. Singleton - конфигурация
  2. Factory - создание объектов
  3. Builder - построение сложных объектов
  4. Observer - event-driven архитектура
  5. Strategy - различные алгоритмы
  6. Proxy - кэширование
  7. Repository - доступ к данным
  8. Dependency Injection - управление зависимостями

Применение паттернов делает код более гибким, тестируемым и поддерживаемым!

Какие паттерны проектирования реализовывал | PrepBro