Какие паттерны проектирования реализовывал
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерны проектирования: Практический опыт
Введение
Паттерны проектирования - это проверенные решения для повторяющихся проблем в архитектуре и дизайне кода. Я использую их ежедневно в своих проектах.
Порождающие паттерны (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();
}
}
Заключение
Паттерны, которые использую чаще всего:
- Singleton - конфигурация
- Factory - создание объектов
- Builder - построение сложных объектов
- Observer - event-driven архитектура
- Strategy - различные алгоритмы
- Proxy - кэширование
- Repository - доступ к данным
- Dependency Injection - управление зависимостями
Применение паттернов делает код более гибким, тестируемым и поддерживаемым!