Template Pattern

lua-users home
wiki

An implementation of Template Method Pattern (http://en.wikipedia.org/wiki/Template_method_pattern). Uses module as class. One file for each class. Based on Petite Abeille's module usage style. Using C++ example from http://login2win.blogspot.com/2008/06/c-template-pattern.html.

Abstract Base Class: 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



Derived Class: 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



Derived Class: 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



Test:

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)



Output:


>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



Download(5.1): Files:wiki_insecure/template-design-pattern.zip Download(5.2): Files:wiki_insecure/template-design-pattern-5.2.zip

-- HakkiDogusan


RecentChanges · preferences
edit · history
Last edited December 23, 2011 4:24 pm GMT (diff)