範本模式

lua-users home
wiki

範本方法模式的實作 (http://en.wikipedia.org/wiki/Template_method_pattern)。使用模組作為類別。每個類別一個檔案。基於 Petite Abeille 的模組使用方式。使用 http://login2win.blogspot.com/2008/06/c-template-pattern.html 的 C++ 範例。

抽象基本類別:Account

local require        = require
local setmetatable   = setmetatable
local getmetatable   = getmetatable
local error          = error
local assert         = assert
local print          = print

-- module declaration
module(...)
_VERSION = "1.0"

local class = setmetatable( _M, {} )
local meta  = getmetatable( class )

function meta:__tostring()
    return ( "%s/%s" ):format( self._NAME, self._VERSION )
end

function class:__tostring()
    return "Account"
end

-- Abstract Methods
function Start(self)
    error("abstract method: should be implemented by derived")
end

function Allow(self)
    error("abstract method: should be implemented by derived")
end

function End(self)
    error("abstract method: should be implemented by derived")
end

function MaxLimit(self)
    error("abstract method: should be implemented by derived")
end

-- Template Method
function Withdraw(self, amount)
    self:Start()
    
    local limit = self:MaxLimit()
    if amount < limit then
        self:Allow()
    else
        print("Not allowed")
    end
    
    self:End()
end

-- constructor
function meta:__call()
    error("private ctor!")
end

衍生類別:AccountNormal?

local require        = require
local getmetatable   = getmetatable
local setmetatable   = setmetatable
local error          = error
local assert         = assert
local print          = print
local tostring       = tostring

-- module declaration
module(...)
_VERSION = "1.0"

local Account  = require("account")
local class    = setmetatable( _M, {__index = Account} )
local meta     = getmetatable( class )

function meta:__tostring()
    return ( "%s/%s" ):format( self._NAME, self._VERSION )
end

function class:__tostring()
    return "AccountNormal"
end

local ometa = { __index = class, __tostring = function() return "AccountNormal" end }

local function InitInstance(self, name)
    self.name = name or "noname"
    --...
end

-- Implement Abstract Methods
function Start(self)
    print("[" .. self.name .. "] Start ...")
end

function Allow(self)
    print("[" .. self.name .. "] Allow ...")
end

function End(self)
    print("[" .. self.name .. "] End ...")
end

function MaxLimit(self)
    return 1000
end

-- constructor
function meta:__call( name )
    
    local c = setmetatable( {}, ometa )
    InitInstance(c, name)
    
    return c
end

衍生類別:AccountPower?

local require        = require
local getmetatable   = getmetatable
local setmetatable   = setmetatable
local error          = error
local assert         = assert
local print          = print
local tostring       = tostring

-- module declaration
module(...)
_VERSION = "1.0"

local Account  = require("account")
local class    = setmetatable( _M, {__index = Account} )
local meta     = getmetatable( class )

function meta:__tostring()
    return ( "%s/%s" ):format( self._NAME, self._VERSION )
end

function class:__tostring()
    return "AccountPower"
end

local ometa = { __index = class, __tostring = function() return "AccountPower" end }

local function InitInstance(self, name)
    self.name = name or "noname"
    --...
end

-- Implement Abstract Methods
function Start(self)
    print("[" .. self.name .. "] Start ...")
end

function Allow(self)
    print("[" .. self.name .. "] Allow ...")
end

function End(self)
    print("[" .. self.name .. "] End ...")
end

function MaxLimit(self)
    return 5000
end

-- constructor
function meta:__call( name )
    
    local c = setmetatable( {}, ometa )
    InitInstance(c, name)
    
    return c
end

測試

local require = require
local print   = print

local Account       = require("account")
local AccountNormal = require("accountnormal")
local AccountPower  = require("accountpower")

-- local ab = Account() -- error! can't create instance of base class

local an0 = AccountNormal("an0")
an0:Withdraw(1500)

local an1 = AccountNormal("an1")
an1:Withdraw(1500)

local ap0 = AccountPower("ap0")
ap0:Withdraw(1500)

local ap1 = AccountPower("ap1")
ap1:Withdraw(1500)

輸出

>lua main.lua
[an0] Start ...
Not allowed
[an0] End ...
[an1] Start ...
Not allowed
[an1] End ...
[ap0] Start ...
[ap0] Allow ...
[ap0] End ...
[ap1] Start ...
[ap1] Allow ...
[ap1] End ...
>Exit code: 0

下載 (5.1): 檔案:wiki_insecure/template-design-pattern.zip 下載 (5.2): 檔案:wiki_insecure/template-design-pattern-5.2.zip

- HakkiDogusan


最近的變更 · 偏好設定
編輯 · 歷史記錄
最後編輯於 2011 年 12 月 23 日,格林威治時間下午 5:24 (差異)