Перейти к основному содержимому

Паттерн "Прототип" (Prototype) в Java — копирование вместо создания с нуля

Разработчику Архитектору

Обзор паттерна — в порождающих паттернах. Здесь — практический Prototype на Java для объектов с дорогой инициализацией.

Загрузка редактора схем…

Задача паттерна

Prototype позволяет создавать новый объект копированием существующего, без повторной полной инициализации.

Подходит, когда:

  • конструктор тяжелый (загрузка шаблонов, конфигов, внешних ресурсов);
  • объекты отличаются только состоянием;
  • нужно быстро тиражировать заготовки.

Пример — прототип отчета

import java.util.HashMap;
import java.util.Map;

abstract class Report implements Cloneable {
protected String template;
protected DatabaseConnection dbConnection;
protected Map<String, Object> settings;

protected Report() {
this.dbConnection = new DatabaseConnection();
this.settings = loadDefaultSettings();
}

protected Map<String, Object> loadDefaultSettings() {
Map<String, Object> defaults = new HashMap<>();
defaults.put("period", "Q1");
defaults.put("format", "pdf");
return defaults;
}

@Override
public Report clone() {
try {
Report cloned = (Report) super.clone();
cloned.settings = new HashMap<>(this.settings);
return cloned;
} catch (CloneNotSupportedException e) {
throw new IllegalStateException(e);
}
}

abstract void generate();
}

class SalesReport extends Report {
@Override
void generate() {
System.out.println("Генерация отчета по продажам");
}
}

final class DatabaseConnection {
}
Report prototype = new SalesReport();

Report report1 = prototype.clone();
Report report2 = prototype.clone();
report2.settings.put("period", "Q2");

Shallow copy и Deep copy

Тип копииЧто копируется
ShallowПримитивы и ссылки (вложенные объекты общие)
DeepНовые экземпляры вложенных изменяемых объектов

В примере выше settings копируется глубоко относительно Map, чтобы изменения в одном отчете не влияли на другие.


Альтернативы clone()

  • copy constructor: new Report(existing)
  • статический метод: Report.copy(existing)
  • сериализация (реже, обычно дороже по CPU)

Во многих командах Java предпочитают явные copy-constructor методы, потому что Cloneable и clone() исторически считаются не самым удобным API.


См. также

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").