Proxy

Design patterns / Structural patterns
image

local images_created = 0

-- RealSubject
local Image = {}
Image.__index = Image

function Image.new(file_name)
  images_created = images_created + 1
  return setmetatable({file_name = file_name},
                      Image)
end

-- Request()
function Image:draw()
  return "draw " .. self.file_name
end

-- Proxy: the same field and method names;
-- the image is created on the first draw
local ImageProxy = {}
ImageProxy.__index = ImageProxy

function ImageProxy.new(file_name)
  return setmetatable({file_name = file_name},
                      ImageProxy)
end

function ImageProxy:draw()
  self.image = self.image
               or Image.new(self.file_name)
  return self.image:draw()
end

-- Client
local proxy = ImageProxy.new("1.png")
-- No image is needed to answer this
local file_name = proxy.file_name
-- file_name = 1.png
local created_before = images_created
-- created_before = 0

-- The call is passed to the image
local drawn = proxy:draw()
-- drawn = draw 1.png
-- images_created = 1

print("file_name = " .. file_name)
print("created_before = " .. created_before)
print("drawn = " .. drawn)
print("images_created = " .. images_created)


Provide a surrogate or placeholder for another object to control access to it. The proxy implements the interface of the original object.
Read more

The problem. A document contains many large pictures. If the program loads all of them when the document opens, opening is slow, although the user sees only the first page. The code that shows the pictures should stay the same. But loading must wait until a picture is really needed.

The idea. A proxy takes the place of another object, the real subject. It has the same interface, so the client sees no difference between them. The proxy decides when and how the real subject is used. This kind, a virtual proxy, creates the real subject only on the first request and then forwards every call to it. Other kinds of proxy check access rights, keep a cache or reach an object on another computer.

How to read the example. The real subject is an image that is costly to create. The proxy keeps only the file name and an empty place for the image. In most languages the client first asks for the file name, and the proxy answers alone. When the client asks to draw, the proxy creates the real image, keeps it and forwards the call. The client works only with the proxy. In some languages the output also shows the moment when the real image is loaded.

When to use it. Use Proxy to control access to an object without changing the object or its clients. Typical tasks are to delay a costly creation, to check rights or to count calls. Do not use it when the object is cheap and always needed: the extra level only slows the code.

A common mistake. Not keeping the created object. The proxy then creates a new real subject on every call, and the saving is lost.