
-- 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)
Описывает виды создаваемых объектов с помощью прототипа и создает новые объекты путем его копирования.Read moreЗадача. В графическом редакторе есть палитра готовых фигур, и у каждой свои цвет, размер и рамка. Когда пользователь перетаскивает фигуру на страницу, программа должна сделать точно такую же новую фигуру. Если код пользуется конструктором, ему приходится знать точный класс и вручную копировать каждую настройку. Тогда каждый новый вид фигуры меняет этот код. Идея. Прототип - это готовый объект, который умеет себя копировать. У него один метод копирования, часто он называется clone. Клиент держит прототип и просит у него копии. Конкретный класс клиент не называет и не знает, какие поля копируются. Копия начинает с теми же данными, что у оригинала, а дальше два объекта живут независимо. Как читать пример. Прототип - это фигура с одним значением, например цветом или числом сторон. В большинстве языков объект-клиент держит один прототип, а новые фигуры получает только одним способом - просит у него копию. Вывод показывает, что у копий то же значение, что у прототипа. Некоторые примеры показывают ещё, что копия - отдельный объект или что изменение копии не трогает прототип. В языках, где значения никогда не меняются, ничего не копируется: новый вариант - это тот же образец с одним изменённым полем. Когда применять. Прототип нужен, когда объект дорого подготовить, а похожих объектов требуется много. Он помогает и тогда, когда класс создаваемого объекта становится известен только во время работы программы. Для простых объектов с немногими полями он ни к чему: конструктор проще. Частая ошибка. Написать метод копирования только в базовом классе, так что он всегда создаёт базовый объект. Копия конкретного прототипа тогда теряет свой класс. Каждый конкретный прототип должен создавать объект своего класса. |