Прототип

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

#include <iostream>
#include <memory>
using namespace std;

//Prototype
class Shape  {
public:
    string color;

    virtual ~Shape() = default;
    virtual unique_ptr<Shape> clone() const = 0;
};

//ConcretePrototype
class Square: public Shape {
public:
    Square(string color) {
        this->color = color;
    }

    unique_ptr<Shape> clone() const override {
        return make_unique<Square>(*this);
    }
};

//Client
class ShapeMaker {
    Shape* shape;

public:
    ShapeMaker(Shape* shape) {
        this->shape = shape;
    }

    unique_ptr<Shape> makeShape() {
        return shape->clone();
    }
};

Square square("Red");
ShapeMaker maker(&square);

unique_ptr<Shape> square1 = maker.makeShape();
unique_ptr<Shape> square2 = maker.makeShape();

cout << "color1 is "  << square1->color << endl;
cout << "color2 is "  << square2->color;


Описывает виды создаваемых объектов с помощью прототипа и создает новые объекты путем его копирования.
Read more

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

Идея. Прототип - это готовый объект, который умеет себя копировать. У него один метод копирования, часто он называется clone. Клиент держит прототип и просит у него копии. Конкретный класс клиент не называет и не знает, какие поля копируются. Копия начинает с теми же данными, что у оригинала, а дальше два объекта живут независимо.

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

Когда применять. Прототип нужен, когда объект дорого подготовить, а похожих объектов требуется много. Он помогает и тогда, когда класс создаваемого объекта становится известен только во время работы программы. Для простых объектов с немногими полями он ни к чему: конструктор проще.

Частая ошибка. Написать метод копирования только в базовом классе, так что он всегда создаёт базовый объект. Копия конкретного прототипа тогда теряет свой класс. Каждый конкретный прототип должен создавать объект своего класса.