Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерны создания объектов (Creational Patterns)
Краткий ответ
Объекты в Java создаются по одному из пяти основных паттернов проектирования: Singleton, Factory Method, Abstract Factory, Builder и Prototype. Каждый решает определённую задачу при создании объектов.
1. Singleton
Обеспечивает существование только одного экземпляра класса в приложении.
Классический Singleton
public class Database {
private static Database instance;
private Database() {} // приватный конструктор
public static synchronized Database getInstance() {
if (instance == null) {
instance = new Database();
}
return instance;
}
}
Database db1 = Database.getInstance();
Database db2 = Database.getInstance();
System.out.println(db1 == db2); // true
Eager Initialization (потокобезопасно)
public class Database {
private static final Database INSTANCE = new Database();
private Database() {}
public static Database getInstance() {
return INSTANCE;
}
}
Bill Pugh Singleton (современный подход)
public class Database {
private Database() {}
private static class DatabaseHolder {
static final Database INSTANCE = new Database();
}
public static Database getInstance() {
return DatabaseHolder.INSTANCE; // инициализируется при первом обращении
}
}
2. Factory Method
Создает объекты через метод, а не напрямую через конструктор.
// Интерфейс
public interface Logger {
void log(String message);
}
// Реализации
public class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println(message);
}
}
public class FileLogger implements Logger {
@Override
public void log(String message) {
// Запись в файл
}
}
// Factory
public class LoggerFactory {
public static Logger createLogger(String type) {
switch(type.toLowerCase()) {
case "console":
return new ConsoleLogger();
case "file":
return new FileLogger();
default:
throw new IllegalArgumentException("Unknown logger type");
}
}
}
// Использование
Logger logger = LoggerFactory.createLogger("console");
logger.log("Application started");
3. Abstract Factory
Создает семейства объектов, которые работают вместе.
// Интерфейсы
public interface Button {
void render();
}
public interface Checkbox {
void render();
}
// Реализации для Windows
public class WindowsButton implements Button {
@Override
public void render() {
System.out.println("Rendering Windows button");
}
}
public class WindowsCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("Rendering Windows checkbox");
}
}
// Реализации для Mac
public class MacButton implements Button {
@Override
public void render() {
System.out.println("Rendering Mac button");
}
}
public class MacCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("Rendering Mac checkbox");
}
}
// Abstract Factory
public interface UIFactory {
Button createButton();
Checkbox createCheckbox();
}
public class WindowsUIFactory implements UIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
public class MacUIFactory implements UIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
// Использование
public class Application {
private UIFactory factory;
public Application(UIFactory factory) {
this.factory = factory;
}
public void createUI() {
Button button = factory.createButton();
Checkbox checkbox = factory.createCheckbox();
button.render();
checkbox.render();
}
}
UIFactory factory = "mac".equals(System.getProperty("os.name"))
? new MacUIFactory()
: new WindowsUIFactory();
Application app = new Application(factory);
app.createUI();
4. Builder
Построение сложных объектов пошагово.
public class User {
private String name;
private String email;
private String phone;
private LocalDate birthDate;
private boolean verified;
// Builder
public static class Builder {
private String name;
private String email;
private String phone;
private LocalDate birthDate;
private boolean verified;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public Builder phone(String phone) {
this.phone = phone;
return this;
}
public Builder birthDate(LocalDate birthDate) {
this.birthDate = birthDate;
return this;
}
public Builder verified(boolean verified) {
this.verified = verified;
return this;
}
public User build() {
User user = new User();
user.name = this.name;
user.email = this.email;
user.phone = this.phone;
user.birthDate = this.birthDate;
user.verified = this.verified;
return user;
}
}
public String getName() { return name; }
public String getEmail() { return email; }
}
// Использование
User user = new User.Builder()
.name("John Doe")
.email("john@example.com")
.phone("+1234567890")
.verified(true)
.build();
Организации часто используют Lombok для автоматической генерации Builder:
@Data
@Builder
public class User {
private String name;
private String email;
private String phone;
}
// Автоматически генерирует Builder
User user = User.builder()
.name("John")
.email("john@example.com")
.build();
5. Prototype
Создает объекты через копирование существующего объекта.
public class Document implements Cloneable {
private String title;
private List<String> content;
public Document(String title) {
this.title = title;
this.content = new ArrayList<>();
}
@Override
public Document clone() throws CloneNotSupportedException {
Document cloned = (Document) super.clone();
// Глубокое копирование для List
cloned.content = new ArrayList<>(this.content);
return cloned;
}
public void addContent(String text) {
content.add(text);
}
}
// Использование
Document original = new Document("Report");
original.addContent("Important data");
Document copy = original.clone();
copy.addContent("More data"); // исходный не изменился
Сравнение паттернов
| Паттерн | Назначение | Использование |
|---|---|---|
| Singleton | Один экземпляр | Database, Config, Logger |
| Factory | Создание по типу | LoggerFactory, ObjectMapper |
| Abstract Factory | Семейства объектов | UI компоненты, Database drivers |
| Builder | Сложные объекты | User, Order, Request |
| Prototype | Копирование объектов | Cloneable, deep copy |
Spring Framework - встроенные паттерны
Spring активно использует эти паттерны:
// Singleton (Spring Beans по умолчанию)
@Component
public class UserService {
// Один экземпляр на всё приложение
}
// Factory Method (Spring создаёт через factory-method)
@Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new JpaUserRepository(); // Factory method
}
}
// Builder (Spring использует его для сложных объектов)
public class RestTemplate {
// Создаётся через RestTemplateBuilder
}
Лучшие практики
-
Используй Singleton для stateless сервисов
- логирование, конфиг, пулы соединений
-
Используй Factory когда неясен конкретный класс
- выбор реализации во время выполнения
-
Используй Builder для сложных объектов
- много параметров, многие опциональны
-
Избегай Prototype если возможно
- предпочитай конструкторы с параметрами
-
Пусть Spring создаёт объекты
- используй @Component, @Bean вместо ручного создания
Вывод
Паттерны создания объектов - это основа чистой архитектуры. Правильный выбор паттерна делает код более гибким, тестируемым и maintainable. Spring автоматически применяет эти паттерны, но понимание их критично для разработчика Java.