Шаблон Flyweight в Java

Легкая модель в Java

1. обзор

В этой статье мы рассмотрим шаблон проектирования наилегчайшего веса. Этот шаблон используется для уменьшения объема памяти. Это также может улучшить производительность в приложениях, где создание экземпляров объекта обходится дорого.

Проще говоря, шаблон flyweight основан на фабрике, которая перерабатывает созданные объекты, сохраняя их после создания. Каждый раз, когда объект запрашивается, фабрика ищет объект, чтобы проверить, был ли он уже создан. Если это так, возвращается существующий объект, в противном случае создается новый, сохраняется и затем возвращается.

Состояние легковесного объекта состоит из инвариантного компонента, совместно используемого с другими подобными объектами (intrinsic), и альтернативного компонента, которым может управлять клиентский код (extrinsic).

Очень важно, чтобы объекты-легковесы были неизменяемыми: любая операция с состоянием должна выполняться фабрикой.

2. Реализация

Основными элементами шаблона являются:

  • интерфейс, который определяет операции, которые клиентский код может выполнять над объектом flyweight

  • одна или несколько конкретных реализаций нашего интерфейса

  • фабрика для обработки объектов и их кэширования

Давайте посмотрим, как реализовать каждый компонент.

2.1. Интерфейс автомобиля

Для начала создадим интерфейсVehicle. Так как этот интерфейс будет возвращаемым типом фабричного метода, мы должны предоставить все соответствующие методы:

public void start();
public void stop();
public Color getColor();

2.2. Бетонный автомобиль

Затем давайте сделаем классCar как конкретныйVehicle.. Наша машина будет реализовывать все методы интерфейса транспортного средства. Что касается его состояния, то у него будет двигатель и цветовое поле:

private Engine engine;
private Color color;

2.3. Автомобильный Завод

И последнее, но не менее важное: мы создадимVehicleFactory. Создание нового транспортного средства - очень дорогая операция, поэтому фабрика будет создавать только один автомобиль для каждого цвета.

Для этого мы отслеживаем созданные автомобили, используя карту в качестве простого кэша:

private static Map vehiclesCache
  = new HashMap<>();

public static Vehicle createVehicle(Color color) {
    Vehicle newVehicle = vehiclesCache.computeIfAbsent(color, newColor -> {
        Engine newEngine = new Engine();
        return new Car(newEngine, newColor);
    });
    return newVehicle;
}

Обратите внимание, как клиентский код может влиять только на внешнее состояние объекта (цвет нашего транспортного средства), передавая его в качестве аргумента методуcreateVehicle.

3. Случаи применения

3.1. Сжатие данных

Целью легковесного шаблона является сокращение использования памяти за счет совместного использования как можно большего количества данных, следовательно, это хорошая основа для алгоритмов сжатия без потерь. В этом случае каждый объект flyweight действует как указатель, а его внешнее состояние является зависимой от контекста информацией.

Классический пример такого использования - текстовый процессор. Здесь каждый символ - это объект-груз, который разделяет данные, необходимые для рендеринга. В результате, только позиция символа внутри документа занимает дополнительную память.

3.2. Кеширование данных

Многие современные приложения используют кэши для улучшения времени отклика. Шаблон flyweight похож на базовую концепцию кэша и может хорошо подойти для этой цели.

Конечно, есть несколько ключевых отличий в сложности и реализации между этим шаблоном и типичным кешем общего назначения.

4. Заключение

Подводя итог, можно сказать, что этот краткий учебник сфокусирован на шаблоне проектирования в стиле Java в Java. Мы также проверили некоторые из наиболее распространенных сценариев, которые включают шаблон.

Весь код из примеров доступен наthe GitHub project.