观察者模式(lua版本)

这是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" )

 

 
posted @ 2019-06-17 11:14  博_客园的张斯瑞  阅读(639)  评论(0编辑  收藏  举报