Single destroyable instance LUA pattern

While developing with Corona SDK I found myself needing (“wanting”) a specific sort of module.

This modules has the following aspects:

  • There is always <= 1 instance (0 or 1)
  • The instance uses it’s closure to clean-up variables (easier maintenance)
  • Auto-complete must be available (so no dynamic require-ing)
  • The instance should be destroyable from any other module

I came up with a usable solution which can be seen below:

local t = {} local instance local function destroyInstance() display.remove(instance) instance = nil end function t:getInstance() return instance end function t:createInstance(\_params, \_onShow) instance = display.newGroup() local blablaVar = blabla local blablaRect = display.newRect(instance, 0, 0, 100, 100) transition.to(blablaRect, {x = 1000, delta = true, time = 10000}) blablaRect:addEventListener("finalize", function() transition.cancel(blablaRect) end) function instance:destroy() --extra cleanup here if needed, not needed in this case though destroyInstance() end end return t

Usage would be:

In my worldModule for example:

local worldInterfaceBuilder = require("worldInterfaceBuilder") worldInterfaceBuilder:createInstance({ defaultIcon = "run", color = {1, 0, 0} })

In my playerModule for example:

local worldInterfaceBuilder = require("worldInterfaceBuilder") local worldInterfaceInstance = worldInterfaceBuilder:getInstance() worldInterfaceInstance:doCurrencyAnimation() -- or worldInterfaceInstance:getInstance():doCurrencyAnimation

What do you guys think of this solution, could there be any problems with it? Are there any other available solutions?

I tend not to use this sort of thing much in Lua (versus plain old modules), but in languages that encourage or force you to use classes everywhere it’s fairly common, and goes by the name of singleton. Maybe you’ll see some relevant points there.

What is “auto-complete”, in this context?

You’re right about the similarities to the singleton pattern, this is where my idea actually originated from, as i’m a originally a JAVA developer.

Regarding the auto-complete in this context, it is meant in the form of auto-complete in my current IDE (LuaGlider). I’m developing a game that is rather more complex (at least I think so) than most average mobile games. As of this moment I got 221 .lua files whereof a lot of POMs (Plain Old Modules), ~50-100.

I’m developing this game all on my own so maintaining and overseeing everything is a full time task, so by using this pattern I would like to improve the readability of some of my modules.

Below I’m gonna make 2 more examples with the same subject as the example in my first post (the worldInterface), I would love to hear the opinion of you guys how these compares with my “singleton” pattern.

Example1: factory

The factory uses the same technique as my singleton pattern, but it allows you to eventually create multiple instances of the object.

Although the instance must be kept by some other class. For instance in the “world” module.

The worldInterfaceFactory would look something like this:

local t = {} function t:new(\_params) local parentGroup = display.newGroup() local blablaVar = "blabla" local blablaRect = display.newRect(parentGroup, 0, 0, 100, 100) transition.to(blablaRect, {x = 1000, delta = true, time = 10000}) blablaRect:addEventListener("finalize", function() transition.cancel(blablaRect) end) return parentGroup end return t

The would be spawned by my world module, and other classes could access functions in the worldInterface through something like worldModule:getInterface():doCurrencyAnimation() or perhaps by mapping the function in the worldModule (eg. worldModule:doCurrencyAnimationOnInterface())

Example2: Plain Old Module

Atleast I think StarCrunch meant this kind of module. It would look something like this:

local t = {} local parentGroup local blablaVar local blablaRect function t:init(\_params) parentGroup = display.newGroup() blablaVar = "blabla" blablaRect = display.newRect(parentGroup, 0, 0, 100, 100) transition.to(blablaRect, {x = 1000, delta = true, time = 10000}) blablaRect:addEventListener("finalize", function() transition.cancel(blablaRect) end) end function t:destroy() display.remove(parentGroup) parentGroup = nil blablaVar = nil blablaRect = nil end return t

Just one small thing I’d possibly add to the start of your createInstance() function:

function t:createInstance(\_params, \_onShow) if instance then return --or "return instance" if the function is setup to return the object after creating it end instance = display.newGroup() local blablaVar = blabla local blablaRect = display.newRect(instance, 0, 0, 100, 100) transition.to(blablaRect, {x = 1000, delta = true, time = 10000}) blablaRect:addEventListener("finalize", function() transition.cancel(blablaRect) end) function instance:destroy() --extra cleanup here if needed, not needed in this case though destroyInstance() end end

This way you cannot accidentally create a second display group and assign that to the instance variable (if the createInstance function is called again by mistake), leaving the original display group unassigned to any named variable.

I tend not to use this sort of thing much in Lua (versus plain old modules), but in languages that encourage or force you to use classes everywhere it’s fairly common, and goes by the name of singleton. Maybe you’ll see some relevant points there.

What is “auto-complete”, in this context?

You’re right about the similarities to the singleton pattern, this is where my idea actually originated from, as i’m a originally a JAVA developer.

Regarding the auto-complete in this context, it is meant in the form of auto-complete in my current IDE (LuaGlider). I’m developing a game that is rather more complex (at least I think so) than most average mobile games. As of this moment I got 221 .lua files whereof a lot of POMs (Plain Old Modules), ~50-100.

I’m developing this game all on my own so maintaining and overseeing everything is a full time task, so by using this pattern I would like to improve the readability of some of my modules.

Below I’m gonna make 2 more examples with the same subject as the example in my first post (the worldInterface), I would love to hear the opinion of you guys how these compares with my “singleton” pattern.

Example1: factory

The factory uses the same technique as my singleton pattern, but it allows you to eventually create multiple instances of the object.

Although the instance must be kept by some other class. For instance in the “world” module.

The worldInterfaceFactory would look something like this:

local t = {} function t:new(\_params) local parentGroup = display.newGroup() local blablaVar = "blabla" local blablaRect = display.newRect(parentGroup, 0, 0, 100, 100) transition.to(blablaRect, {x = 1000, delta = true, time = 10000}) blablaRect:addEventListener("finalize", function() transition.cancel(blablaRect) end) return parentGroup end return t

The would be spawned by my world module, and other classes could access functions in the worldInterface through something like worldModule:getInterface():doCurrencyAnimation() or perhaps by mapping the function in the worldModule (eg. worldModule:doCurrencyAnimationOnInterface())

Example2: Plain Old Module

Atleast I think StarCrunch meant this kind of module. It would look something like this:

local t = {} local parentGroup local blablaVar local blablaRect function t:init(\_params) parentGroup = display.newGroup() blablaVar = "blabla" blablaRect = display.newRect(parentGroup, 0, 0, 100, 100) transition.to(blablaRect, {x = 1000, delta = true, time = 10000}) blablaRect:addEventListener("finalize", function() transition.cancel(blablaRect) end) end function t:destroy() display.remove(parentGroup) parentGroup = nil blablaVar = nil blablaRect = nil end return t

Just one small thing I’d possibly add to the start of your createInstance() function:

function t:createInstance(\_params, \_onShow) if instance then return --or "return instance" if the function is setup to return the object after creating it end instance = display.newGroup() local blablaVar = blabla local blablaRect = display.newRect(instance, 0, 0, 100, 100) transition.to(blablaRect, {x = 1000, delta = true, time = 10000}) blablaRect:addEventListener("finalize", function() transition.cancel(blablaRect) end) function instance:destroy() --extra cleanup here if needed, not needed in this case though destroyInstance() end end

This way you cannot accidentally create a second display group and assign that to the instance variable (if the createInstance function is called again by mistake), leaving the original display group unassigned to any named variable.