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

По какому шаблону создаются объекты

1.2 Junior🔥 241 комментариев
#Основы Java

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

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

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

Паттерны создания объектов (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
}

Лучшие практики

  1. Используй Singleton для stateless сервисов

    • логирование, конфиг, пулы соединений
  2. Используй Factory когда неясен конкретный класс

    • выбор реализации во время выполнения
  3. Используй Builder для сложных объектов

    • много параметров, многие опциональны
  4. Избегай Prototype если возможно

    • предпочитай конструкторы с параметрами
  5. Пусть Spring создаёт объекты

    • используй @Component, @Bean вместо ручного создания

Вывод

Паттерны создания объектов - это основа чистой архитектуры. Правильный выбор паттерна делает код более гибким, тестируемым и maintainable. Spring автоматически применяет эти паттерны, но понимание их критично для разработчика Java.