Prototype

Design patterns / Creational patterns
image

//Prototype: a pointer to a function plays the virtual clone()
typedef struct Shape {
    const char *color;
    struct Shape *(*clone)(const struct Shape *self);
} Shape;

//ConcretePrototype: the base struct is the first field
typedef struct {
    Shape base;
} Square;

//only the concrete type knows its size, so it makes the copy;
//assigning a struct copies all its fields
Shape *squareClone(const Shape *self) {
    Square *copy = malloc(sizeof *copy);
    *copy = *(const Square *)self;
    return &copy->base;
}

//Client
typedef struct {
    const Shape *shape;
} ShapeMaker;

Shape *makeShape(const ShapeMaker *maker) {
    return maker->shape->clone(maker->shape);
}

Square square = {{"Red", squareClone}};
ShapeMaker maker = {&square.base};

Shape *square1 = makeShape(&maker);
Square *square2 = (Square *)makeShape(&maker);
//square1->color is "Red"
//square2->base.color is "Red"
bool same = square1 == &square2->base;
//same is false: each call makes a new copy

printf("color1 is %s\n", square1->color);
printf("color2 is %s\n", square2->base.color);
printf("same is %s\n", same ? "true" : "false");
free(square1);
free(square2);


Specify the kinds of objects to create using a prototypical instance, and create new objectsby copying this prototype.
Read more

The problem. A drawing program has a palette of ready shapes, each with its own colour, size and border. When the user drags a shape onto the page, the program must make a new shape just like it. If the code uses a constructor, it must know the exact class and copy every setting by hand. Each new kind of shape then changes this code.

The idea. A prototype is a ready object that knows how to copy itself. It has one copy method, often called clone. The client keeps a prototype and asks it for copies. It does not name the concrete class and does not know which fields are copied. A copy starts with the same data as the original, and after that the two objects are independent.

How to read the example. The prototype is a shape with one value, such as a colour or a number of sides. In most languages a client object keeps one prototype and makes new shapes only by asking it for a copy. The output shows that the copies have the same value as the prototype. Some examples also show that a copy is a separate object, or that a change to the copy leaves the prototype unchanged. In languages where values never change, nothing is copied: a variant is the same sample with one field changed.

When to use it. Use Prototype when an object is costly to prepare and many similar objects are needed. It also helps when the class to create is known only while the program runs. Do not use it for simple objects with few fields: a constructor is simpler.

A common mistake. Writing the copy method only in the base class, so that it always creates a base object. A copy of a concrete prototype then loses its own class. Each concrete prototype must create an object of its own class.