
-- ConcretePrototype
local Square = {}
Square.__index = Square
function Square.new(color)
return setmetatable({color = color}, Square)
end
-- A new table with the same fields
-- and the same class
function Square:clone()
local copy = {}
for key, value in pairs(self) do
copy[key] = value
end
return setmetatable(copy, getmetatable(self))
end
-- Client: makes shapes from a prototype
-- without naming its class
local function shape_maker(shape)
return function()
return shape:clone()
end
end
local square = Square.new("Red")
local make_shape = shape_maker(square)
local square1 = make_shape()
local square2 = make_shape()
local same = square1 == square2
-- same = false
-- No copy at all: an empty table that reads
-- missing fields from the prototype
local linked =
setmetatable({}, {__index = square})
-- It follows the prototype, a clone does not
square.color = "Blue"
-- linked.color = Blue
-- square1.color = Red
print("same = " .. tostring(same))
print("linked.color = " .. linked.color)
print("square1.color = " .. square1.color)
Specify the kinds of objects to create using a prototypical instance, and create new objectsby copying this prototype.Read moreThe 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. |