← Назад к вопросам
С какими шаблонами проектирования работал
1.2 Junior🔥 181 комментариев
#ORM и Hibernate#Spring Boot и Spring Data#Базы данных и SQL
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Шаблоны проектирования (Design Patterns) в моей практике
В своей разработке применял множество шаблонов из классификации Gang of Four и архитектурные паттерны. Опишу наиболее часто используемые с практическими примерами.
Creational Patterns (Порождающие)
1. Singleton
// Используется для единственного экземпляра ресурса
public class DatabaseConnectionPool {
private static DatabaseConnectionPool instance;
private final DataSource dataSource;
private DatabaseConnectionPool() {
this.dataSource = createDataSource();
}
public static synchronized DatabaseConnectionPool getInstance() {
if (instance == null) {
instance = new DatabaseConnectionPool();
}
return instance;
}
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
// Более безопасный вариант
public class DatabaseConnectionPool {
private static final DatabaseConnectionPool INSTANCE =
new DatabaseConnectionPool();
private DatabaseConnectionPool() {}
public static DatabaseConnectionPool getInstance() {
return INSTANCE;
}
}
2. Factory Pattern
// Создание семейства объектов без привязки к конкретным классам
public interface PaymentProcessor {
void process(Payment payment);
}
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void process(Payment payment) {
System.out.println("Processing credit card payment");
}
}
public class PayPalProcessor implements PaymentProcessor {
@Override
public void process(Payment payment) {
System.out.println("Processing PayPal payment");
}
}
public class PaymentProcessorFactory {
public static PaymentProcessor createProcessor(PaymentMethod method) {
return switch(method) {
case CREDIT_CARD -> new CreditCardProcessor();
case PAYPAL -> new PayPalProcessor();
case BANK_TRANSFER -> new BankTransferProcessor();
default -> throw new IllegalArgumentException("Unknown method");
};
}
}
// Использование
public class OrderService {
public void checkout(Order order) {
PaymentProcessor processor =
PaymentProcessorFactory.createProcessor(order.getPaymentMethod());
processor.process(order.getPayment());
}
}
3. Builder Pattern
// Для построения сложных объектов с множеством параметров
public class UserDto {
private final String email;
private final String firstName;
private final String lastName;
private final int age;
private final String phone;
private final String address;
private UserDto(Builder builder) {
this.email = builder.email;
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
public static class Builder {
private final String email;
private String firstName;
private String lastName;
private int age;
private String phone;
private String address;
public Builder(String email) {
this.email = email;
}
public Builder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder lastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public UserDto build() {
return new UserDto(this);
}
}
}
// Использование
UserDto user = new UserDto.Builder("john@example.com")
.firstName("John")
.lastName("Doe")
.age(30)
.phone("+1234567890")
.build();
Structural Patterns (Структурные)
1. Proxy Pattern
// Контролированный доступ к объекту
public interface UserService {
User getUser(Long id);
void updateUser(User user);
}
public class UserServiceImpl implements UserService {
@Override
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
@Override
public void updateUser(User user) {
userRepository.save(user);
}
}
public class UserServiceProxy implements UserService {
private final UserService userService;
private final SecurityContext securityContext;
public UserServiceProxy(UserService userService,
SecurityContext securityContext) {
this.userService = userService;
this.securityContext = securityContext;
}
@Override
public User getUser(Long id) {
if (!securityContext.hasPermission("read_user")) {
throw new AccessDeniedException("Access denied");
}
return userService.getUser(id);
}
@Override
public void updateUser(User user) {
if (!securityContext.hasPermission("write_user")) {
throw new AccessDeniedException("Access denied");
}
userService.updateUser(user);
}
}
2. Decorator Pattern
// Динамическое расширение функциональности объектов
public interface Coffee {
double cost();
String description();
}
public class SimpleCoffee implements Coffee {
@Override
public double cost() {
return 2.0;
}
@Override
public String description() {
return "Simple coffee";
}
}
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return coffee.cost() + 0.5;
}
@Override
public String description() {
return coffee.description() + ", milk";
}
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return coffee.cost() + 0.2;
}
@Override
public String description() {
return coffee.description() + ", sugar";
}
}
// Использование
Coffee coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
System.out.println(coffee.description()); // Simple coffee, milk, sugar
System.out.println(coffee.cost()); // 2.7
3. Adapter Pattern
// Преобразование несовместимых интерфейсов
public interface PaymentGateway {
boolean pay(String accountNumber, BigDecimal amount);
}
public class LegacyPaymentSystem {
public boolean processPayment(String account, double amount) {
System.out.println("Legacy system processing: " + amount);
return true;
}
}
public class PaymentGatewayAdapter implements PaymentGateway {
private final LegacyPaymentSystem legacySystem;
public PaymentGatewayAdapter(LegacyPaymentSystem legacySystem) {
this.legacySystem = legacySystem;
}
@Override
public boolean pay(String accountNumber, BigDecimal amount) {
return legacySystem.processPayment(accountNumber, amount.doubleValue());
}
}
Behavioral Patterns (Поведенческие)
1. Strategy Pattern
// Выбор алгоритма в runtime
public interface SortingStrategy {
void sort(int[] array);
}
public class QuickSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// QuickSort реализация
}
}
public class MergeSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// MergeSort реализация
}
}
public class DataSorter {
private SortingStrategy strategy;
public void setStrategy(SortingStrategy strategy) {
this.strategy = strategy;
}
public void sort(int[] array) {
strategy.sort(array);
}
}
// Использование
DataSorter sorter = new DataSorter();
sorter.setStrategy(new QuickSort());
sorter.sort(array);
sorter.setStrategy(new MergeSort());
sorter.sort(array);
2. Observer Pattern
// Event-driven архитектура
public interface OrderObserver {
void update(Order order);
}
public class EmailNotifier implements OrderObserver {
@Override
public void update(Order order) {
System.out.println("Sending email for order: " + order.getId());
}
}
public class SMSNotifier implements OrderObserver {
@Override
public void update(Order order) {
System.out.println("Sending SMS for order: " + order.getId());
}
}
public class OrderManager {
private final List<OrderObserver> observers = new ArrayList<>();
public void registerObserver(OrderObserver observer) {
observers.add(observer);
}
public void removeObserver(OrderObserver observer) {
observers.remove(observer);
}
public void notifyObservers(Order order) {
for (OrderObserver observer : observers) {
observer.update(order);
}
}
public void placeOrder(Order order) {
// Логика обработки заказа
notifyObservers(order);
}
}
3. Command Pattern
// Инкапсуляция запроса как объекта
public interface Command {
void execute();
void undo();
}
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() {
from.deposit(amount);
to.withdraw(amount);
}
}
public class TransactionManager {
private final List<Command> commandHistory = new ArrayList<>();
public void execute(Command command) {
command.execute();
commandHistory.add(command);
}
public void undoLastCommand() {
if (!commandHistory.isEmpty()) {
Command lastCommand = commandHistory.remove(commandHistory.size() - 1);
lastCommand.undo();
}
}
}
4. State Pattern
// Изменение поведения объекта при смене состояния
public interface OrderState {
void processOrder(Order order);
void cancelOrder(Order order);
}
public class PendingState implements OrderState {
@Override
public void processOrder(Order order) {
System.out.println("Processing order...");
order.setState(new ProcessingState());
}
@Override
public void cancelOrder(Order order) {
System.out.println("Order cancelled");
order.setState(new CancelledState());
}
}
public class ProcessingState implements OrderState {
@Override
public void processOrder(Order order) {
System.out.println("Shipping order...");
order.setState(new ShippedState());
}
@Override
public void cancelOrder(Order order) {
System.out.println("Cannot cancel while processing");
}
}
public class Order {
private OrderState state = new PendingState();
public void processOrder() {
state.processOrder(this);
}
public void setState(OrderState state) {
this.state = state;
}
}
Архитектурные паттерны
1. MVC (Model-View-Controller)
Использую в Spring MVC приложениях.
2. Repository Pattern
public interface UserRepository {
User findById(Long id);
void save(User user);
void delete(Long id);
}
public class UserRepositoryImpl implements UserRepository {
private final DataSource dataSource;
@Override
public User findById(Long id) {
// Database query
}
@Override
public void save(User user) {
// Database insert/update
}
}
3. Dependency Injection
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;
}
}
4. Aspect-Oriented Programming (AOP)
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logMethodExecution(ProceedingJoinPoint joinPoint)
throws Throwable {
long startTime = System.currentTimeMillis();
try {
return joinPoint.proceed();
} finally {
long duration = System.currentTimeMillis() - startTime;
System.out.println("Method " + joinPoint.getSignature() +
" took " + duration + "ms");
}
}
}
Итого
Часто используемые:
- Factory (для создания объектов)
- Strategy (для выбора алгоритма)
- Observer (для event-driven систем)
- Decorator (для расширения функциональности)
- Builder (для сложных объектов)
Менее часто, но когда нужны:
- Command (для undo/redo)
- State (для конечных автоматов)
- Proxy (для контроля доступа)
- Adapter (для интеграции legacy систем)
Знание паттернов позволяет писать более гибкий, поддерживаемый и расширяемый код.