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

Приведи пример порождающего паттерна

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

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

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

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

Порождающие паттерны проектирования

Порождающие паттерны — это паттерны, которые фокусируются на создании объектов гибким способом, скрывая детали создания и конкретные классы. Они включают: Singleton, Factory Method, Abstract Factory, Builder и Prototype.

Рассмотрим несколько практических примеров.

Пример 1: Builder Pattern

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

// Плохо: конструктор с множеством параметров
public class DatabaseConfig {
    public DatabaseConfig(String host, int port, String username, String password,
                         int maxConnections, int timeout, boolean useSSL,
                         String databaseName) {
        // инициализация...
    }
}

// Использование — непонятно что это
DatabaseConfig config = new DatabaseConfig("localhost", 5432, "admin", "password",
                                           50, 30000, true, "mydb");

Решение с Builder:

public class DatabaseConfig {
    private final String host;
    private final int port;
    private final String username;
    private final String password;
    private final int maxConnections;
    private final int timeout;
    private final boolean useSSL;
    private final String databaseName;
    
    private DatabaseConfig(Builder builder) {
        this.host = builder.host;
        this.port = builder.port;
        this.username = builder.username;
        this.password = builder.password;
        this.maxConnections = builder.maxConnections;
        this.timeout = builder.timeout;
        this.useSSL = builder.useSSL;
        this.databaseName = builder.databaseName;
    }
    
    public static class Builder {
        private String host = "localhost";
        private int port = 5432;
        private String username;
        private String password;
        private int maxConnections = 10;
        private int timeout = 30000;
        private boolean useSSL = false;
        private String databaseName;
        
        public Builder host(String host) {
            this.host = host;
            return this;
        }
        
        public Builder port(int port) {
            this.port = port;
            return this;
        }
        
        public Builder credentials(String username, String password) {
            this.username = username;
            this.password = password;
            return this;
        }
        
        public Builder maxConnections(int maxConnections) {
            this.maxConnections = maxConnections;
            return this;
        }
        
        public Builder timeout(int timeout) {
            this.timeout = timeout;
            return this;
        }
        
        public Builder useSSL(boolean useSSL) {
            this.useSSL = useSSL;
            return this;
        }
        
        public Builder database(String databaseName) {
            this.databaseName = databaseName;
            return this;
        }
        
        public DatabaseConfig build() {
            if (username == null || password == null || databaseName == null) {
                throw new IllegalArgumentException("Required fields missing");
            }
            return new DatabaseConfig(this);
        }
    }
}

// Использование — ясно и читаемо
DatabaseConfig config = new DatabaseConfig.Builder()
    .host("prod-db.example.com")
    .port(5432)
    .credentials("admin", "securePassword")
    .maxConnections(100)
    .timeout(60000)
    .useSSL(true)
    .database("production")
    .build();

Преимущества Builder:

  • Читаемость и ясность
  • Гибкость с параметрами
  • Возможность установки значений по умолчанию
  • Валидация в методе build()

Пример 2: Factory Method Pattern

Проблема: Нужно создавать разные типы объектов в зависимости от условий.

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 {
    private String filePath;
    
    public FileLogger(String filePath) {
        this.filePath = filePath;
    }
    
    @Override
    public void log(String message) {
        // запись в файл
        System.out.println("[FILE] " + filePath + ": " + message);
    }
}

public class LoggerFactory {
    public static Logger createLogger(String type) {
        switch(type.toLowerCase()) {
            case "console":
                return new ConsoleLogger();
            case "file":
                return new FileLogger("logs/app.log");
            case "database":
                return new DatabaseLogger();
            default:
                throw new IllegalArgumentException("Unknown logger type: " + type);
        }
    }
}

// Использование
Logger logger = LoggerFactory.createLogger("console");
logger.log("Application started");

Преимущества Factory Method:

  • Централизованное создание объектов
  • Легко добавлять новые типы
  • Клиент не знает о конкретных классах

Пример 3: Singleton Pattern

public class DatabaseConnectionPool {
    private static DatabaseConnectionPool instance;
    private List<Connection> connections;
    
    private DatabaseConnectionPool() {
        // приватный конструктор
        this.connections = new ArrayList<>();
    }
    
    // Thread-safe singleton
    public static synchronized DatabaseConnectionPool getInstance() {
        if (instance == null) {
            instance = new DatabaseConnectionPool();
        }
        return instance;
    }
    
    public Connection getConnection() {
        // логика получения соединения
        return connections.get(0);
    }
}

// Использование
DatabaseConnectionPool pool = DatabaseConnectionPool.getInstance();
Connection conn = pool.getConnection();

Лучший вариант — Eager initialization:

public class DatabaseConnectionPool {
    private static final DatabaseConnectionPool INSTANCE = 
        new DatabaseConnectionPool();
    
    private DatabaseConnectionPool() {}
    
    public static DatabaseConnectionPool getInstance() {
        return INSTANCE;
    }
}

Вывод

Порождающие паттерны решают задачу создания объектов:

  • Builder — для сложных объектов с множеством параметров
  • Factory Method — для гибкого создания разных типов
  • Singleton — для единственного экземпляра ресурса
  • Abstract Factory — для семейств связанных объектов
  • Prototype — для копирования существующих объектов

Правильное использование этих паттернов делает код гибким, тестируемым и легко расширяемым.