这是Observer Design Pattern 的一个实现,它利用了闭包。
-- 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", observer, method ) -- subject:reg( "signal", nil, function ) -- subject:notify( "signal" ) -- subject:dereg( "signal", observer, method ) -- subject:dereg( "signal", nil, function )
-- 用法示例:
-- subject.reg,subject.dereg,subject.notify = observer.create()
-- 主题:reg(“信号”,观察者,方法)
-- 主题:reg(“信号”,零,功能)
-- 主题:通知(“信号”)
-- 主题:dereg(“信号”,观察者,方法)
-- subject:dereg(“signal”,nil,function)
local table = require("table"); local base = require("base"); local setmetatable = base.setmetatable local ipairs = base.ipairs module("observer") function create() -- Containter holds the filter, and handlers and observers. local container = {} -- Provision for garbage collection, weak metatable and sentinel. local weak = { __mode = "kv" } -- Register -- Creates an observation between the Subject data and the -- Observer data, using filter Signal and handler Method. -- Usage: -- s:register( "update", o, o.m )
-- 注册
-- 在主题数据和主题数据之间创建观察
-- 观察者数据,使用过滤器信号和处理程序方法。
-- 用法:
-- s:register(“update”,o,o.m)
local register = function( subject, signal, observer, method ) t = container[signal] or {} local o = observer or weak local k = { method, o } setmetatable( k, weak ) table.insert( t, k ) container[signal] = t end -- Deregister -- Removes any observations in the Signal filter, either matching -- the Observer and Method, or the whole filter if both are nil. -- Usage: -- s:deregister( "update" ) -- s:deregister( "update", o ) -- s:deregister( "update", o, o.m )
-- 取消注册
-- 删除信号过滤器中的任何观察结果,或者匹配
-- 观察者和方法,或整个过滤器,如果两者都是零。
-- 用法:
-- s:注销(“更新”)
-- s:deregister(“update”,o)
-- s:deregister(“update”,o,o.m)
local deregister = function( subject, signal, observer, method ) t = container[signal] if not t then return end if not method and not observer then container[signal] = nil return end local i, v i = #t while i > 0 do v = t[i] or {} if ( not method or v[1] == method ) and ( not observer or v[2] == observer ) then table.remove( t, i ) end i = i - 1 end end
-- Notify -- Uses the Signal Filter to notify all observations via their -- registered handlers. -- Usage: -- s:notify( "update" )
-- 通知
-- 使用信号过滤器通过它们通知所有观察结果
-- 注册处理程序。
-- 用法:
-- s:通知(“更新”)
local notify = function( subject, signal, ... ) t = container[signal] if not t then return end for i, v in ipairs( t ) do if v[2] == weak then v[1](subject, ...) elseif v[2] then v[1](v[2], subject, ...) end -- garbage collected observers (nil) are skipped. end end return register, deregister, notify end -- Signal -- Convienience function that gives a shorthand to sending a -- notification. -- Usage: -- s.update = signal( s, s.notify, "update" ) -- s.update()
-- 信号
-- 便捷功能,提供发送的速记
-- 通知。
-- 用法:
-- s.update = signal(s,s.notify,“update”)
-- s.update()
function signal( subject, notify, name ) return function( ... ) return notify( subject, name, ... ) end end
这是一个示例用法。请注意,observer.signal函数有助于创建一种语法,有点模仿C ++框架Qt的信号和插槽模型
require("observer") -- Observers. function a( subject ) print( "a", type(subject) ) end function b( data, subject, extra ) print( "b", data, type(subject), extra ) end o = {} function o:m( subject, extra ) print( "o:m", type(self), type(subject), extra ) end -- First Observation reg, dereg, notify = observer.create() reg( nil, "signal", nil, a ) reg( nil, "signal", "lol", b ) print( "First notification" ) notify( nil, "signal", "zomg" ) dereg( nil, "signal", nil, a ) print( "Second notification" ) notify( nil, "signal" ) -- Second Observation s = {} s.reg, s.dereg, s.notify = observer.create() s.signal = observer.signal( s, s.notify, "signal" ) s:reg( "signal", nil, a ) s:reg( "signal", o, o.m ) print( "Third notification" ) s.signal("rofl") s:dereg( "signal" ) s:reg( "signal", o, o.m ) print( "Fourth notification" ) o = nil collectgarbage() s:notify( "signal" )