Паттерн «Прототип»

Шаблон «Прототип» используется для создания дублирующихся объектов, обеспечивая при этом производительность. Этот тип шаблонов проектирования относится к порождающим шаблонам и предоставляет один из лучших способов создания объектов.

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

summary

Паттерн «Прототип»

назначение: Используйте экземпляры прототипа, чтобы указать виды создаваемых объектов, и создавайте новые объекты путем копирования этих прототипов.

В основном решает: Динамически создавать и удалять прототипы во время выполнения.

Когда использовать

  • Система не зависит от создания, композиции и представления продуктов.
  • Класс для создания экземпляра должен быть указан во время выполнения, например, посредством динамической загрузки.
  • Избегайте создания иерархии классов фабрик, параллельной иерархии классов продуктов.
  • Экземпляры класса могут иметь лишь несколько различных комбинаций состояний; клонирование прототипа удобнее ручного создания экземпляров.

Как решить

Быстро создавать экземпляр, идентичный объекту-прототипу, используя существующий объект-прототип.

Ключевой код

  • Реализуйте операцию clone:
    • В Java реализуйтеCloneableИнтерфейс, переопределитьclone()метод.
    • В .NET используйтеObjectКлассMemberwiseClone()Метод реализует поверхностное копирование или глубокое копирование через сериализацию.
  • Изолируйте связь между пользователями объектов классов и конкретными типами, требуя, чтобы "volatile classes" имели стабильные интерфейсы.

Пример приложения

  • Деление клетки
  • На JavaObject.clone()Методы

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

  • Повышение производительности
  • Избегание ограничений конструктора

Недостатки

  • Оснащение класса методами clone требует всестороннего учёта функциональности класса, что может быть сложно для существующих классов, особенно при работе с косвенными объектами, не поддерживающими сериализацию, или ссылками, содержащими циклические структуры.
  • Обязательная реализацияCloneableИнтерфейс.

Сценарий использования

  • Оптимизация ресурсов
  • Когда инициализация класса потребляет большой объём ресурсов (таких как данные, аппаратные ресурсы).
  • Сценарии с высокими требованиями к производительности и безопасности
  • ЧерезnewКогда создание объекта требует сложной подготовки данных или прав доступа.
  • Объект требует нескольких модификаторов
  • Когда объект нужно предоставить другим объектам для доступа, и он может быть изменён различными вызывающими сторонами.
  • Часто используется вместе с паттерном фабричного метода, посредствомcloneсоздания объектов, которые затем предоставляются вызывающим сторонам фабричным методом.

Примечания

В отличие от прямого создания экземпляра класса для создания нового объекта, паттерн Прототип создаёт новые объекты путём копирования существующих объектов. Поверхностное копирование достигается путём реализацииCloneableтогда как глубокое копирование достигается путём реализацииSerializableчтения двоичных потоков.

Структура

Паттерн прототип включает следующие основные роли:

  • Интерфейс прототипа: Определяет интерфейс для клонирования самого себя, обычно включающийclone()метод.

  • Конкретный прототип: Конкретный класс, который реализует интерфейс прототипа и отвечает за фактическую операцию клонирования. Этот класс должен реализоватьclone()метод, обычно используя поверхностное или глубокое копирование для копирования самого себя.

  • Клиент: использует экземпляры прототипа для создания новых объектов. Клиент вызывает у объекта-прототипаclone()метод для создания новых объектов вместо прямого использования конструкторов.

Реализация

Мы создадим абстрактный классShapeи расширяющиеShapeконкретные классы этого класса. Следующий шаг — определить классShapeCache, этот класс хранит объекты фигур вHashtableи возвращает их клоны по запросу.

PrototypePatternDemoКласс используетShapeCacheкласс для полученияShapeобъекта.

原型模式的 UML 图

Шаг 1

Создайте абстрактный класс, которыйCloneableреализует интерфейс.

Shape.java

public abstract class Shape implements Cloneable { private String id; protected String type; abstract void draw(); public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } }

Шаг 2

Создайте классы сущностей, расширяющие вышеуказанный абстрактный класс.

Rectangle.java

public class Rectangle extends Shape { public Rectangle(){ type = "Rectangle"; } @Override public void draw() { System.out.println("Внутри метода Rectangle::draw()."); } }

Square.java

public class Square extends Shape { public Square(){ type = "Square"; } @Override public void draw() { System.out.println("Внутри метода Square::draw()."); } }

Circle.java

public class Circle extends Shape { public Circle(){ type = "Circle"; } @Override public void draw() { System.out.println("Внутри метода Circle::draw()."); } }

Шаг 3

Создайте класс, который извлекает классы сущностей из базы данных и сохраняет их вHashtableВ.

ShapeCache.java

import java.util.Hashtable; public class ShapeCache { private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>(); public static Shape getShape(String shapeId) { Shape cachedShape = shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } //Выполните запрос к базе данных для каждой фигуры и создайте эту фигуру // shapeMap.put(shapeKey, shape); //Например, мы хотим добавить три фигуры public static void loadCache() { Circle circle = new Circle(); circle.setId("1"); shapeMap.put(circle.getId(),circle); Square square = new Square(); square.setId("2"); shapeMap.put(square.getId(),square); Rectangle rectangle = new Rectangle(); rectangle.setId("3"); shapeMap.put(rectangle.getId(),rectangle); } }

Шаг 4

PrototypePatternDemoИспользованиеShapeCacheкласс для получения прототипа, хранящегося вHashtableклона фигуры внутри.

PrototypePatternDemo.java

public class PrototypePatternDemo { public static void main(String[] args) { ShapeCache.loadCache(); Shape clonedShape = (Shape) ShapeCache.getShape("1"); System.out.println("Shape : " + clonedShape.getType()); Shape clonedShape2 = (Shape) ShapeCache.getShape("2"); System.out.println("Shape : " + clonedShape2.getType()); Shape clonedShape3 = (Shape) ShapeCache.getShape("3"); System.out.println("Shape : " + clonedShape3.getType()); } }

Шаг 5

Запустите программу, выведите результат:

Shape : Circle
Shape : Square
Shape : Rectangle
Другие расширения