Alternative Observer Pattern |
|
module(..., package.seeall) -- Register local function register( self, observer, method ) local t = {} t.o = observer t.m = method table.insert( self, t ) end -- Deregister local function deregister( self, observer, method ) local i local n = #self for i = n, 1, -1 do if (not observer or self[i].o == observer) and (not method or self[i].m == method) then table.remove( self, i ) end end end -- Notify local function notify( self, ... ) local i local n = #self for i = 1, n do self[i].m( self[i].o, ... ) end end -- signal metatable local mt = { __call = function( self, ... ) self:notify(...) end } function signal() local t = {} t.register = register t.deregister = deregister t.notify = notify setmetatable( t, mt ) return t end
Because the signals are now explicit objects, instead of implicit data (such as a string), we use the table syntactic sugar to work with them. The __call metamethod is included for convenience, so that we can use the signal directly.
observer = require( "alt_obs" ) alice = {} function alice:slot( param ) print( self, param ) end bob = {} bob.alert = observer.signal() bob.alert:register( alice, alice.slot ) bob.alert( "Hi there" ) bob.alert:deregister( alice ) bob.alert( "Hello?" )
-- WilliamBubel