Creating Singletons

"In object-oriented programming, the singleton pattern is a software design pattern that restricts the instantiation of a class to a singular instance"

Quebec uses singletons to define the behavior of your game. This happens through services which are server-side singletons that handle game logic, and through controllers which are the client-side equivalent of a service.

Singletons can implement lifecycle events to act upon various inputs. The most common one is the start lifecycle event, which is fired as soon as your singleton starts.

Example Singleton (works as both controller & service)
local Singleton = {
    lifecycles = { "start" } -- declares usage of the start lifecycle (required)
}

function Singleton:start()
    print(game:GetService("RunService"):IsClient())
end

return Singleton

The above snippet can run as both a controller and a service, because it doesn't rely on environment-specific functions. On the client, this would print true and on the server it would print false.

🛠️ Adding an initialization function

You can add an initialization function inside your singleton which gets called before it is started. You shouldn't yield in this function, but you can load dependencies using the first parameter. The signature for this function is: (Singleton, DependencyResolver) -> nil

local Singleton = {}

function Singleton:init(resolver)
    self.foo = resolver("@quebec/foo")
end

return Singleton

Last updated