← Назад к вопросам
Приведи пример порождающего паттерна
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 — для копирования существующих объектов
Правильное использование этих паттернов делает код гибким, тестируемым и легко расширяемым.