lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I wrote this in anticipation of a future project and would like some
code review, along with any and all questions, suggestions, or
criticisms that go with it. Thanks in advance.

-- Observer design pattern.
-- Produces a few functions that have a closure that implements
-- subject-observer notification.

-- Example usage:
-- subject.reg, subject.dereg, subject.notify = observer.create()
-- subject.reg( "signal", method, observer )
-- subject.reg( "signal", function )
-- subject.notify( "signal", subject )
-- subject.dereg( "signal", method, observer )
-- subject.dereg( "signal", function )

local setmetatable = _G.setmetatable
local ipairs = _G.ipairs
local table = require("table");

module("observer")

function create( t )
  -- Container houses signals that contain a list of observer/slot
relationships.
  local container = {}
  local weak = { __mode = "kv" }

  local register = function( signal, method, observer )
    t = container[signal] or {}
    local k = { method, observer }
    setmetatable( k, weak )
    table.insert( t, k )
    container[signal] = t
  end

  local deregister = function( signal, method, observer )
    if not method and not observer and container[signal] then
      container[signal] = nil
      return
    end

    t = container[signal]
    if not t then return end
    local i=#t, v;
    while i > 0 do
      v = t[i]
      if  ( not method   or v[1] == method )
      and ( not observer or v[2] == observer ) then
        table.remove( t, i )
      end
      i = i - 1
    end

    for i, v in ipairs( t ) do
    end
  end

  local notify = function( signal, subject )
    t = container[signal]
    if not t then return end
    for i, v in ipairs( t ) do
      if v[2] then
        v[1](v[2], subject)
      else
        v[1](subject)
      end
    end
  end

  if not t then
    return register, deregister, notify
  end

  local obj_reg = function( self, signal, method, observer )
    return register( signal, method, observer )
  end

  local obj_dereg = function( self, signal, method, observer )
    return deregister( signal, method, observer )
  end

  local obj_notify = function( self, signal )
    return notify( signal, self )
  end

  return obj_reg, obj_dereg, obj_notify
end

-- EOF