├── state ├── readme ├── read.md ├── main.lua ├── state_study.lua ├── state.lua ├── state_sleep.lua ├── state_work.lua ├── context.lua └── simple.lua ├── composite ├── read.md └── composite.lua ├── instance ├── read.md ├── test.lua ├── simple.lua └── single.lua ├── iterator ├── read.md └── iterator.lua ├── memento ├── read.md ├── simple.lua └── memento.lua ├── strategy ├── strategy.lua ├── strategy_normal.lua ├── strategy_off.lua ├── strategy_return.lua ├── context.lua ├── context_factory.lua └── main.lua ├── observe ├── fan.lua ├── publish.lua ├── main.lua └── simple_ob.lua ├── decorator ├── oo.lua └── decorator.lua ├── template_method └── template_method.lua ├── README.md ├── proxy └── proxy.lua ├── simple_factory └── simple_factory.lua ├── factory_method └── factory_method.lua └── facade └── facade.lua /state/readme: -------------------------------------------------------------------------------- 1 | 状态模式的示例代码 2 | -------------------------------------------------------------------------------- /composite/read.md: -------------------------------------------------------------------------------- 1 | **组合模式** 2 | -------------------------------------------------------------------------------- /instance/read.md: -------------------------------------------------------------------------------- 1 | **单例模式** 2 | -------------------------------------------------------------------------------- /iterator/read.md: -------------------------------------------------------------------------------- 1 | **迭代器模式** 2 | -------------------------------------------------------------------------------- /memento/read.md: -------------------------------------------------------------------------------- 1 | **备忘录模式** 2 | -------------------------------------------------------------------------------- /state/read.md: -------------------------------------------------------------------------------- 1 | 2 | **状态模式** 3 | -------------------------------------------------------------------------------- /instance/test.lua: -------------------------------------------------------------------------------- 1 | local t = { 2 | [1] = {jf}, 3 | } 4 | 5 | -------------------------------------------------------------------------------- /strategy/strategy.lua: -------------------------------------------------------------------------------- 1 | -- 定义算法家族 2 | -- 父类 3 | -- 并且需要符合依赖倒转原则 4 | local _M = {} 5 | 6 | function _M:new(o) 7 | o = o or {} 8 | 9 | setmetatable(o, self) 10 | self.__index = self 11 | 12 | return o 13 | end 14 | 15 | function _M:algoInterface(input) 16 | end 17 | 18 | return _M 19 | -------------------------------------------------------------------------------- /observe/fan.lua: -------------------------------------------------------------------------------- 1 | -- 观察者类 2 | local observer = {} 3 | function observer:new( o ) 4 | o = o or {} 5 | o.subject = o.subject or {} 6 | setmetatable(o, self) 7 | self.__index = self 8 | return o 9 | end 10 | 11 | -- 当 subject 更新状态(notify) 执行的反应 12 | function observer:update() 13 | end 14 | 15 | return observer -------------------------------------------------------------------------------- /state/main.lua: -------------------------------------------------------------------------------- 1 | local context = require "context" 2 | local stateWork = require "state_work" 3 | 4 | -- 生成一个context实例,成员有hour=9 5 | local c = context:new() 6 | local s = stateWork:new() 7 | c:setState(s) 8 | 9 | c.hour = 10 10 | c:request() 11 | c.hour = 9 12 | c:request() 13 | 14 | c.hour = 13 15 | c:request() 16 | 17 | c.hour = 16 18 | c:request() 19 | -------------------------------------------------------------------------------- /strategy/strategy_normal.lua: -------------------------------------------------------------------------------- 1 | -- 策略子类 2 | -- 正常收费,无优惠 3 | local strategy = require "strategy" 4 | local _M = strategy:new() 5 | 6 | -- function _M:new(o) 7 | -- o = o or {} 8 | 9 | -- setmetatable(o, self) 10 | -- self.__index = self 11 | 12 | -- return o 13 | -- end 14 | 15 | function _M:algoInterface(input) 16 | return input 17 | end 18 | 19 | return _M 20 | -------------------------------------------------------------------------------- /strategy/strategy_off.lua: -------------------------------------------------------------------------------- 1 | -- 策略子类 2 | -- 打折: 3 | local strategy = require "strategy" 4 | local _M = strategy:new() 5 | 6 | function _M:new(o) 7 | o = o or {} 8 | o.off = o.off or 0 9 | 10 | setmetatable(o, self) 11 | self.__index = self 12 | 13 | return o 14 | end 15 | 16 | function _M:algoInterface(input) 17 | return input * (self.off) 18 | end 19 | 20 | return _M 21 | -------------------------------------------------------------------------------- /state/state_study.lua: -------------------------------------------------------------------------------- 1 | -- 学习状态 2 | local state = require "state" 3 | -- local stateStudy = require "state_study" 4 | 5 | -- 继承自state 6 | local _M = state:new() 7 | 8 | function _M:date(context) 9 | -- 由于变化是有前置步骤的,所以这里不用完整判断 10 | if context.hour < 18 then 11 | print("学习") 12 | else 13 | -- self.context:setState(stateStudy:new()) 14 | end 15 | end 16 | 17 | return _M 18 | -------------------------------------------------------------------------------- /strategy/strategy_return.lua: -------------------------------------------------------------------------------- 1 | -- 策略子类 2 | -- 满减: 3 | local strategy = require "strategy" 4 | local _M = strategy:new() 5 | 6 | function _M:new(o) 7 | o = o or {} 8 | o.l = o.l or 0 9 | o.off = o.off or 0 10 | 11 | setmetatable(o, self) 12 | self.__index = self 13 | 14 | return o 15 | end 16 | 17 | function _M:algoInterface(input) 18 | return input > self.l and (input - self.off) or input 19 | end 20 | 21 | return _M 22 | -------------------------------------------------------------------------------- /state/state.lua: -------------------------------------------------------------------------------- 1 | -- 状态 2 | -- 定义一个接口以封装与context的一个特定状态相关的行为 3 | local _M = {} 4 | 5 | function _M.new(self, opt) 6 | opt = opt or {} 7 | 8 | self.__index = self 9 | setmetatable(opt, self) 10 | return opt 11 | end 12 | 13 | function _M.setContext(self, context) 14 | self.context = context -- context对象 15 | end 16 | 17 | -- 安排,也就是统一接口 18 | -- context 维护state类的上下文 19 | function _M.date(self, context) 20 | end 21 | 22 | return _M 23 | 24 | -------------------------------------------------------------------------------- /strategy/context.lua: -------------------------------------------------------------------------------- 1 | -- context,保留父类策略的引用,利用多态来执行具体的策略 2 | -- 但是lua的多态不能像java那样(否则需要自己设计一个class) 3 | local _M = {} 4 | 5 | function _M:new(o) 6 | o = o or {} 7 | o.strategy = o.strategy or {} -- class 8 | 9 | setmetatable(o, self) 10 | self.__index = self 11 | -- self._strategy = {} -- class 12 | 13 | return o 14 | end 15 | 16 | function _M:interface(input) 17 | -- 这个就是最后相同的公共结果 18 | return self.strategy:algoInterface(input) 19 | end 20 | 21 | return _M 22 | -------------------------------------------------------------------------------- /state/state_sleep.lua: -------------------------------------------------------------------------------- 1 | -- 中午睡觉吃饭状态 2 | local state = require "state" 3 | local stateStudy = require "state_study" 4 | 5 | -- 继承自state 6 | local _M = state:new() 7 | 8 | function _M:date(context) 9 | -- 由于变化是有前置步骤的,所以这里不用完整判断 10 | if context.hour <= 14 then 11 | print("吃饭,睡觉") 12 | else 13 | -- 睡觉完就学习 14 | -- 将状态更改为学习的状态 15 | local s = stateStudy:new() 16 | context:setState(s) 17 | context:request() 18 | end 19 | end 20 | 21 | return _M 22 | -------------------------------------------------------------------------------- /state/state_work.lua: -------------------------------------------------------------------------------- 1 | -- 上班状态 2 | local state = require "state" 3 | local stateSleep = require "state_sleep" 4 | 5 | -- 继承自state 6 | local _M = state:new() 7 | 8 | function _M:date(context) 9 | if context.hour >= 9 and context.hour < 12 then 10 | print("上班") 11 | else 12 | -- 上班后去吃饭 13 | -- 将状态更改为中午睡觉的状态 14 | local s = stateSleep:new() 15 | context:setState(s) 16 | context:request() -- 需要再驱动一次,不然没有成功转变状态 17 | end 18 | end 19 | 20 | 21 | return _M 22 | -------------------------------------------------------------------------------- /state/context.lua: -------------------------------------------------------------------------------- 1 | -- context类,维护一个具体的state实例,这个实例描述当前状态 2 | local _M = {} 3 | -- local stateWork = require "state_work" 4 | 5 | 6 | function _M.new(self, opt) 7 | opt = opt or {} 8 | -- 当前时间 9 | opt.hour = opt.hour or 9 10 | 11 | self.__index = self 12 | setmetatable(opt, self) 13 | return opt 14 | end 15 | 16 | function _M:setState(state) 17 | self.state = state 18 | end 19 | 20 | -- 状态变化统一调用接口 21 | function _M:request() 22 | self.state:date(self) 23 | end 24 | 25 | return _M 26 | -------------------------------------------------------------------------------- /instance/simple.lua: -------------------------------------------------------------------------------- 1 | local win = {} 2 | 3 | function win:new(opt) 4 | opt = opt or {} 5 | 6 | self.__index = self 7 | setmetatable(opt, self) 8 | return opt 9 | end 10 | 11 | 12 | 13 | ---继承自win 多个子类 14 | local win1 = win:new() 15 | local win2 = win:new() 16 | local win3 = win:new() 17 | local win4 = win:new() 18 | local win5 = win:new() 19 | 20 | 21 | 22 | 23 | --- 记录实例化次数 24 | local win1Num = 0 25 | local win2Num = 0 26 | local win3Num = 0 27 | local win4Num = 0 28 | local win5Num = 0 29 | 30 | 31 | 32 | 33 | 34 | ---main 35 | local w1 36 | if win1Num == 0 then 37 | w1 = win1:new() 38 | end 39 | 40 | -------------------------------------------------------------------------------- /strategy/context_factory.lua: -------------------------------------------------------------------------------- 1 | -- 使用简单工厂模式将判断逻辑转移至内部 2 | local strategyReturn = require "strategy_return" 3 | local strategyOff = require "strategy_off" 4 | 5 | local _M = {} 6 | 7 | 8 | function _M:new(o) 9 | o = o or {} 10 | 11 | if o.t == 1 then 12 | o.strategy = strategyReturn:new({ l = 200, off = 20 }) 13 | elseif o.t == 2 then 14 | o.strategy = strategyOff:new({ off = 0.3 }) 15 | end 16 | 17 | setmetatable(o, self) 18 | self.__index = self 19 | 20 | return o 21 | end 22 | 23 | function _M:interface(input) 24 | -- 这个就是最后相同的公共结果 25 | return self.strategy:algoInterface(input) 26 | end 27 | 28 | return _M 29 | -------------------------------------------------------------------------------- /state/simple.lua: -------------------------------------------------------------------------------- 1 | 2 | local _M = {} 3 | 4 | function _M.new(self, opt) 5 | opt = opt or {} 6 | opt.hour = opt.hour or 9 7 | 8 | self.__index = self 9 | setmetatable(opt, self) 10 | return opt 11 | end 12 | 13 | function _M.date(self) 14 | if self.hour > 9 and self.hour < 12 then 15 | print("上班") 16 | elseif self.hour < 14 then 17 | print("吃饭, 睡觉") 18 | elseif self.hour < 18 then 19 | print("学习") 20 | end 21 | end 22 | 23 | -------------------------------------------- 24 | 25 | local o = _M:new({hour = 9}) 26 | o.hour = 10 27 | o:date() 28 | o.hour = 11 29 | o:date() 30 | o.hour = 12 31 | o:date() 32 | o.hour = 16 33 | o:date() 34 | 35 | 36 | -------------------------------------------------------------------------------- /observe/publish.lua: -------------------------------------------------------------------------------- 1 | -- 主题类 2 | local subject = {} 3 | function subject:new( o ) 4 | o = o or {} 5 | o.observer = o.observer or {} 6 | setmetatable(o, self) 7 | self.__index = self 8 | return o 9 | end 10 | 11 | -- 通知状态接口 12 | function subject:notify() 13 | for _, observer in ipairs(self.observer) do 14 | observer:update() 15 | end 16 | end 17 | 18 | -- 增加一个被通知的观察者 19 | function subject:attach(observer) 20 | table.insert(self.observer, observer) 21 | end 22 | 23 | -- 剔除一个被通知的观察者 24 | function subject:detach(observerToBeDetach) 25 | for index, observer in ipairs(self.observer) do 26 | -- 会自动调用 _eq 元方法, 但是两者一样的话就不会调用, 27 | -- 直接是相等,或者可以使用 rawequal 28 | if observer == observerToBeDetach then 29 | table.remove(self.observer, index) 30 | end 31 | end 32 | end 33 | 34 | return subject -------------------------------------------------------------------------------- /instance/single.lua: -------------------------------------------------------------------------------- 1 | local single = { 2 | isNew = false 3 | } 4 | 5 | 6 | 7 | 8 | -- 获得实例 9 | function single.getInstance(self, opt) 10 | 11 | -- 私有构造 12 | local function new(self, opt) 13 | opt = opt or {} 14 | 15 | self.__index = self 16 | setmetatable(opt, self) 17 | return opt 18 | end 19 | 20 | -- 如果已经实例化过 不返回一个实例 21 | if single.isNew then 22 | return nil 23 | else 24 | single.isNew = true 25 | return new(self, opt) 26 | end 27 | end 28 | 29 | function single:getIsNew() 30 | print(self.isNew) 31 | end 32 | 33 | 34 | 35 | 36 | -- local s = single:getInstance() 37 | -- print(s:getIsNew()) 38 | -- local s1 = single:getInstance() 39 | -- print(s1:getIsNew()) 40 | local win = single:getInstance() 41 | -- print(win:getIsNew()) 42 | local win2 = single:getInstance() 43 | if not win2 then 44 | print("win2 isnt instance") 45 | end 46 | 47 | 48 | -------------------------------------------------------------------------------- /strategy/main.lua: -------------------------------------------------------------------------------- 1 | local context = require "context" 2 | local strategyReturn = require "strategy_return" 3 | local strategyOff = require "strategy_off" 4 | 5 | -- 策略模式 6 | -- 封装的变化点是算法的不一致,将他们封装起来,互不影响,但求得结果的目的是一致的 7 | -- 也就是公共算法结果 8 | -- 比如商场优惠策略是不同的,但是最后都是要求出优惠价 9 | -- 像满100 送20 200送30 打八折 三折 10 | -- 就可以抽象为满减,正常收费,打折三种算法 11 | -- 这个想法很重要 12 | 13 | 14 | 15 | -- 满200送20 16 | local sr = strategyReturn:new({ l = 200, off = 20 }) 17 | local ctxtR = context:new({ strategy = sr }) 18 | print(ctxtR:interface(300)) 19 | print(ctxtR:interface(100)) 20 | 21 | -- 打三折 22 | local ctxtO = context:new({ strategy = strategyOff:new({ off = 0.3 }) }) 23 | print(ctxtO:interface(300)) 24 | print(ctxtO:interface(100)) 25 | 26 | -- 这样可以看出,context只需要传入具体的策略,统一调用interface接口即可 27 | -- 现在我需要根据一个值来切换不同的优惠策略,那么我就需要使用if-elseif-else分支进行判断 28 | -- 如果要将这种逻辑转移,可以利用之前学习的简单工厂模式 29 | -- 但是我不太清楚是否违背开放-封闭原则 30 | local contextFac = require "context_factory" 31 | 32 | -- 这样只需要一个判断值,连具体策略也进行屏蔽,做到了更深层解耦 33 | -- 但是这样在contextfac中就需要不断地增加分支判断,仍然不够通用,依旧存在缺点 34 | local ctxtFac = contextFac:new({ t = 2 }) -- 打折策略 35 | print(ctxtFac:interface(400)) 36 | 37 | 38 | -------------------------------------------------------------------------------- /memento/simple.lua: -------------------------------------------------------------------------------- 1 | local role = {} 2 | 3 | function role.new(self, opt) 4 | opt = opt or {} 5 | 6 | -- 生命值 7 | opt.hp = opt.hp or 100 8 | -- 魔法值 9 | opt.mp = opt.mp or 100 10 | -- 经验值 11 | opt.exp = opt.exp or 0 12 | 13 | self.__index = self 14 | setmetatable(opt, self) 15 | return opt 16 | end 17 | 18 | 19 | function role.fight(self) 20 | self.hp = 0 21 | self.mp = 0 22 | self.exp = 0 23 | end 24 | 25 | function role:show() 26 | print(self.hp) 27 | print(self.mp) 28 | print(self.exp) 29 | end 30 | 31 | 32 | -- function _M:setHp(hp) 33 | -- self.hp = hp 34 | -- end 35 | 36 | -- function _M:setMp(mp) 37 | -- end 38 | 39 | -- function _M:setExp(exp) 40 | -- end 41 | -- 42 | 43 | -- 默认生命,魔法各100,经验为0 44 | local r = role:new() 45 | 46 | 47 | -- 备份操作,生成一个新实例 48 | local t = role:new() 49 | -- 这里就当做是get接口将r的数据通过set接口传给了t 50 | t.hp = r.hp 51 | t.mp = r.mp 52 | t.exp = r.exp 53 | print("fight before") 54 | r:show() 55 | 56 | r:fight() 57 | print("fight done") 58 | r:show() 59 | 60 | 61 | -- 回档操作 62 | r.hp = t.hp 63 | r.mp = t.mp 64 | r.exp = t.exp 65 | print("recover") 66 | r:show() 67 | 68 | 69 | -------------------------------------------------------------------------------- /decorator/oo.lua: -------------------------------------------------------------------------------- 1 | -- 原先的面向对象方式节省空间,但是没有 super 这个功能 2 | -- 所以还是写一个拓展,参考了岩哥、云风代码 3 | 4 | -- 用于生成一个类 5 | function class( super ) 6 | -- 一个类 7 | local cls = {} 8 | 9 | if super then 10 | -- 子类在高层,找不到再往元表 11 | setmetatable(cls, {__index = super}) 12 | cls.super = super 13 | end 14 | 15 | -- 父类也要生成实例 16 | -- 生成实例 17 | function cls.new(self, ... ) 18 | -- 同理,实例在高层,找不到再往元表走 19 | local instance = setmetatable({}, {__index = cls}) 20 | 21 | -- 实例化过程 22 | local create 23 | create = function ( c, ... ) 24 | -- 获得 super 但是为了不触发元表,使用 rawget 25 | local superCls = rawget(c, "super") 26 | if superCls then 27 | create(superCls, ...) 28 | end 29 | 30 | -- 获得构造函数 31 | local ctor = rawget(c, "ctor") 32 | if ctor then 33 | ctor(c, ...) 34 | end 35 | end 36 | create(cls, ...) 37 | 38 | return instance 39 | end 40 | 41 | -- cls 自带 cls.new。所以 new 函数中,需要传入 cls 作为 self 42 | return cls 43 | end 44 | 45 | function new(cls, ...) 46 | return cls.new( ... ) 47 | end 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /template_method/template_method.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | local flight = {} 4 | 5 | function flight:new( o ) 6 | o = o or {} 7 | 8 | setmetatable(o, self) 9 | self.__index = self 10 | 11 | return o 12 | end 13 | 14 | -- 很明显,降落和起飞点也可以成为一个属性 15 | -- function flight:setFromAndTo( from, to ) 16 | -- self.from = from 17 | -- self.to = to 18 | -- end 19 | 20 | -- 起飞 operation1 21 | function flight:takeOff() 22 | end 23 | 24 | -- 降落 operation2 25 | function flight:arrive() 26 | end 27 | 28 | -- 一次航班,也就是 templateMethod 29 | -- 这里定义了逻辑步骤 30 | function flight:oneFlight() 31 | self:takeOff() 32 | self:arrive() 33 | end 34 | 35 | -- 继承自 flight 36 | local flight1 = flight:new() 37 | 38 | function flight1:takeOff() 39 | print("先买个鱼丸") 40 | print("从福州起飞") 41 | end 42 | 43 | function flight1:arrive() 44 | print("鱼丸汤扔了") 45 | print("在厦门降落") 46 | end 47 | 48 | 49 | 50 | 51 | -- 继承自 flight 52 | local flight2 = flight:new() 53 | 54 | function flight2:takeOff() 55 | print("先买个米线糊") 56 | print("从厦门起飞") 57 | end 58 | 59 | function flight2:arrive() 60 | print("糊吃完了") 61 | print("在北京降落") 62 | end 63 | 64 | local f1 = flight1:new() 65 | f1:oneFlight() 66 | 67 | print('----------') 68 | local f2 = flight2:new() 69 | f2:oneFlight() 70 | 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 设计模式学习 2 | **本仓库是设计模式学习的源码托管,使用 lua 语言实现。限于个人 lua 接触的时间不足和对设计模式的使用还没有完全应用于实践,对设计模式的 lua 实现存在一定的不足,望各位多批评指正.** 3 | 4 | **个人对设计模式的理解托管在有道云笔记。目前更新内容如下,仍是欢迎各位批评指正。** 5 | 6 | * [单一职责、开放封闭、依赖倒转原则](http://note.youdao.com/noteshare?id=0bea989de95eda0c1080bf5432789fd5) 7 | * [组合模式](http://note.youdao.com/noteshare?id=74c1a29732eac84fbe6055dcb55898c8) 8 | * [单例模式](http://note.youdao.com/noteshare?id=87c874f350184781c3ece32f607f0134) 9 | * [迭代器模式](http://note.youdao.com/noteshare?id=2acff105403cb863f3c7bb72e864c54d) 10 | * [备忘录模式](http://note.youdao.com/noteshare?id=36af32739ae9d0b765e692a385f2807a) 11 | * [简单工厂模式](http://note.youdao.com/noteshare?id=a866f270ff2f6d826a4a848ad2d49a7c) 12 | * [状态模式](http://note.youdao.com/noteshare?id=cb5bbee03c10503bd13d30fe25f19080) 13 | * [策略模式](http://note.youdao.com/noteshare?id=be3d3754ac772ac6b59af81b99977802) 14 | * [装饰模式](http://note.youdao.com/noteshare?id=ad4fa754f96fd531ad103ab3dfc92f46) 15 | * [代理模式](http://note.youdao.com/noteshare?id=10fa2a933ca824a3bc3544f21cb42321) 16 | * [工厂方法模式](http://note.youdao.com/noteshare?id=5083a2b7c90930dbe4b8ab671f96ad9e) 17 | * [模板方法模式](http://note.youdao.com/noteshare?id=494fa1e96648433e299279f8896815e1) 18 | * [外观模式](http://note.youdao.com/noteshare?id=757d16d0d91ce4a7465751391f508c25) 19 | * [建造者模式](http://note.youdao.com/noteshare?id=f8506266eab5335353125349a7c55135) 20 | * [观察者模式](http://note.youdao.com/noteshare?id=b71d1fbfb46f968f44161189c7687ee7) 21 | 22 | 23 | --- 24 | 25 | **联系方式:545749402@qq.com** 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /proxy/proxy.lua: -------------------------------------------------------------------------------- 1 | -------------giveGift---------------- 2 | local giveGift = {} -- 送礼物,追女生的公共方法 3 | 4 | function giveGift:new(o) 5 | o = o or {} 6 | -- o.girl = o.girl or "" 7 | 8 | setmetatable(o, self) 9 | self.__index = self 10 | 11 | return o 12 | end 13 | 14 | -- 以下为公共接口, 供子类重写 15 | -- 被追的是谁 16 | function giveGift:setGirl( girl ) 17 | self.girl = girl 18 | end 19 | 20 | -- 送花 21 | function giveGift:giveFlower() 22 | -- print("give you flower " .. self.girl) 23 | end 24 | 25 | -- 送吃得 26 | function giveGift:giveFood() 27 | -- print("give you food " .. self.girl) 28 | end 29 | -------------giveGift end---------------- 30 | 31 | -------------pursuit---------------- 32 | local pursuit = giveGift:new() -- 追求者,realSubject 33 | 34 | function pursuit:giveFlower() 35 | print("give you flower " .. self.girl) 36 | end 37 | 38 | function pursuit:giveFood() 39 | print("give you food " .. self.girl) 40 | end 41 | 42 | -------------pursuit end---------------- 43 | 44 | 45 | 46 | -------------proxy---------------- 47 | local proxy = giveGift:new() 48 | 49 | 50 | function proxy:setGirl(girl) 51 | self.realPursuit = pursuit:new() 52 | self.realPursuit:setGirl(girl) 53 | end 54 | 55 | -- 实际是 pursuit 调用方法 56 | function proxy:giveFlower() 57 | if self.realPursuit then 58 | print(self.realPursuit:giveFlower()) 59 | end 60 | end 61 | 62 | function proxy:giveFood() 63 | if self.realPursuit then 64 | print(self.realPursuit:giveFood()) 65 | end 66 | end 67 | 68 | 69 | -------------proxy end---------------- 70 | 71 | local p = proxy:new() 72 | p:setGirl("jinse") 73 | p:giveFlower() 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /observe/main.lua: -------------------------------------------------------------------------------- 1 | local fan = require "fan" 2 | local publish = require "publish" 3 | -- 为了文件不太多,就这样 4 | 5 | -- 写文章公众号 6 | local articlePub = publish:new() 7 | 8 | -- 制作推文 9 | -- 一种状态改变 10 | function articlePub:produceContent(content) 11 | print("制作一篇文章") 12 | self.content = content 13 | end 14 | 15 | 16 | -- 主攻视频的公众号 17 | local videoPub = publish:new() 18 | 19 | function videoPub:produceContent(content) 20 | print("制作一个视频") 21 | self.content = content 22 | end 23 | 24 | -------------------- 25 | 26 | -- 黑粉 27 | local blackFans = fan:new() 28 | 29 | -- 接收到推文的反应 30 | function blackFans:update() 31 | print("辣鸡 " .. self.subject.content) 32 | end 33 | 34 | 35 | -- 忠实粉 36 | local goodFans = fan:new() 37 | 38 | -- 接收到推文的反应 39 | function goodFans:update() 40 | print("打赏,转发 " .. self.subject.content) 41 | end 42 | 43 | -------------------- 44 | 45 | -- 文章公众号 46 | local articlePubish = articlePub:new() 47 | -- 视频公众号 48 | local videoPubish = videoPub:new() 49 | 50 | -- 关注文章公号的黑粉 51 | local blackFanTom4article = blackFans:new {subject = articlePubish} 52 | local blackFanAmy4video = blackFans:new {subject = videoPubish} 53 | 54 | -- 关注文章公号的忠实粉丝 55 | local goodFanZyt4article = goodFans:new {subject = articlePubish} 56 | -- 关注视频公号的忠实粉丝 57 | local goodFanZz4video = goodFans:new {subject = videoPubish} 58 | local goodFanFz4video = goodFans:new {subject = videoPubish} 59 | 60 | articlePubish:attach(blackFanTom4article) 61 | articlePubish:attach(goodFanZyt4article) 62 | videoPubish:attach(blackFanAmy4video) 63 | videoPubish:attach(goodFanZz4video) 64 | videoPubish:attach(goodFanFz4video) 65 | 66 | articlePubish:produceContent("核心对撞 | 金色天际线") 67 | videoPubish:produceContent("金色的一天 | 金色天际线") 68 | print("发布文章------------------") 69 | articlePubish:notify() 70 | videoPubish:notify() 71 | 72 | -------------------------------------------------------------------------------- /simple_factory/simple_factory.lua: -------------------------------------------------------------------------------- 1 | -- 简单工厂模式 2 | -- 计算器示例 3 | -- 工厂根据一个类型来生成不一样的类的实例,而这个实例需要有一个抽象的父类 4 | 5 | -- 为什么要有这个模式,拿计算器来说,加减乘除其实只是运算符号不一,剩下的得出结果,需要的参数是统一的。如果为了这个而不断地使用判断语句,是浪费效率的 6 | -- 把加减乘除抽出来一个运算类,而这些又是这个运算类的子类,方便加减乘除的额外操作修改,修改一个操作不影响其他操作,进行很好地分离 7 | -- 不仅如此,这样拥有了更好的扩展性,维护性增加。 8 | 9 | -- 运算类 10 | local baseOp = { n = "base" } 11 | 12 | 13 | -- 我操我知道了,我真的GG。 14 | -- 首先,子类继承的时候也就是通过baseOp:new()的时候,子类addOp元表就是baseOp,分析一下self就可以得到这个结论 15 | -- 那么addOp实例画的时候,等于是一个新的table,元表是addOp,执行一个函数的时候,先去addOp找,没有,就通过addOp元表找,也就是baseOp 16 | -- 困扰我很久的一点也就来了,难道不会一值递归查找吗,因为baseOp.__index是自己 17 | -- 但是我忘记了,baseOp没有setmetatable,所以到baseOp就不会继续执行__index元方法了。 18 | function baseOp:new(o) 19 | o = o or {} 20 | 21 | setmetatable(o, self) 22 | self.__index = self 23 | 24 | return o 25 | end 26 | 27 | function baseOp:setParam(num1, num2) 28 | self.num1 = num1 29 | self.num2 = num2 30 | end 31 | 32 | -- 抽象方法 33 | function baseOp:operate() 34 | end 35 | 36 | -- 加法运算类 37 | -- 继承自baseOp 38 | -- baseOp实例,通过元表可访问baseOp function 39 | -- 但是addOp:new() 通过元表调用了new(), self 是addOp 40 | local addOp = baseOp:new() 41 | -- addOp:setParam(1, 3) 42 | 43 | function addOp:operate() 44 | return self.num1 + self.num2 45 | end 46 | 47 | 48 | -- 减法运算类 49 | -- 继承自baseOp 50 | local subOp = baseOp:new() 51 | 52 | function subOp:operate() 53 | return self.num1 - self.num2 54 | end 55 | 56 | 57 | 58 | -- 简单工厂类 59 | local simpleFactory = {} 60 | 61 | function simpleFactory:createOp(t) 62 | if t == "+" then 63 | return addOp:new() 64 | elseif t == "-" then 65 | return subOp:new() 66 | end 67 | end 68 | 69 | function simpleFactory:new(o) 70 | o = o or {} 71 | setmetatable(o, self) 72 | self.__index = self 73 | 74 | return o 75 | end 76 | 77 | local f = simpleFactory:new() 78 | local op = f:createOp("+") 79 | op:setParam(1, 2) 80 | local r = op:operate() 81 | print(r) 82 | -------------------------------------------------------------------------------- /factory_method/factory_method.lua: -------------------------------------------------------------------------------- 1 | -- 这里继续写计算器 2 | 3 | -- 运算类 4 | local operation = {} 5 | 6 | function operation:new( o ) 7 | -- body 8 | o = o or {} 9 | setmetatable(o, self) 10 | self.__index = self 11 | 12 | return o 13 | end 14 | 15 | function operation:setNums( num1, num2 ) 16 | self._num1 = num1 17 | self._num2 = num2 18 | end 19 | 20 | -- 运算的公共接口 21 | -- 等待子类重写 22 | function operation:getResult() 23 | -- body 24 | end 25 | 26 | -- 加法运算类 27 | local operationAdd = operation:new() 28 | 29 | function operationAdd:getResult() 30 | return self._num1 + self._num2 31 | end 32 | 33 | -- 减法运算类 34 | local operationSub = operation:new() 35 | 36 | function operationSub:getResult() 37 | return self._num1 - self._num2 38 | end 39 | 40 | -- 乘法运算类 41 | local operationMul = operation:new() 42 | 43 | function operationMul:getResult() 44 | return self._num1 * self._num2 45 | end 46 | 47 | 48 | 49 | -- 工厂的抽象 50 | local factory = {} 51 | 52 | function factory:new( o ) 53 | -- body 54 | o = o or {} 55 | 56 | setmetatable(o, self) 57 | self.__index = self 58 | 59 | return o 60 | end 61 | 62 | -- 工厂的公共接口 63 | -- sheng 64 | function factory:createOperation() 65 | -- body 66 | end 67 | 68 | -- 具体的工厂 - 加法工厂 69 | local factoryAdd = factory:new() 70 | 71 | function factoryAdd:createOperation() 72 | return operationAdd:new() 73 | end 74 | 75 | 76 | -- 具体的工厂 - 减法工厂 77 | local factorySub = factory:new() 78 | 79 | function factorySub:createOperation() 80 | return operationSub:new() 81 | end 82 | 83 | 84 | -- 具体的工厂 - 乘法工厂 85 | local factoryMul = factory:new() 86 | 87 | function factoryMul:createOperation() 88 | return operationMul:new() 89 | end 90 | 91 | 92 | 93 | local facAdd = factoryAdd:new() 94 | local facSub = factorySub:new() 95 | 96 | local opAdd = facAdd:createOperation() 97 | local opSub = facSub:createOperation() 98 | 99 | 100 | -- 这样具体用add 还是 sub。需要具体调用,或者说客户端来决定。 101 | opAdd:setNums(1, 2) 102 | print(opAdd:getResult()) 103 | 104 | opSub:setNums(1, 2) 105 | print(opSub:getResult()) 106 | 107 | 108 | -------------------------------------------------------------------------------- /observe/simple_ob.lua: -------------------------------------------------------------------------------- 1 | -- 公众号类 2 | local publish = {} 3 | 4 | function publish:new( o ) 5 | -- body 6 | o = o or {} 7 | o.followers = o.followers or {} 8 | o.article = o.article or "" 9 | setmetatable(o, self) 10 | self.__index = self 11 | 12 | return o 13 | end 14 | 15 | -- 被关注 16 | function publish:beFollow( follower ) 17 | table.insert(self.followers, follower) 18 | end 19 | 20 | 21 | -- 被取关 22 | function publish:beCancelFollow() 23 | end 24 | 25 | -- 写一个推文 26 | function publish:wirte(name) 27 | self.article = name 28 | end 29 | 30 | -- 发送推文 31 | function publish:sendMsg() 32 | for _, v in ipairs(self.followers) do 33 | -- 这里使用了 粉丝类 的方法 34 | v:react() 35 | end 36 | end 37 | 38 | 39 | 40 | -- 黑粉 41 | local blackFans = {} 42 | function blackFans:new( o ) 43 | o = o or {} 44 | -- 关注的公众号 45 | o.pub = o.pub or {} 46 | setmetatable(o, self) 47 | self.__index = self 48 | 49 | return o 50 | end 51 | 52 | -- 收到推文的反应 53 | function blackFans:react() 54 | print("辣鸡文章!" .. self.pub.article) 55 | end 56 | 57 | -- 忠实粉 58 | local goodFans = {} 59 | function goodFans:new( o ) 60 | o = o or {} 61 | -- 关注的公众号 62 | o.pub = o.pub or {} 63 | setmetatable(o, self) 64 | self.__index = self 65 | 66 | return o 67 | end 68 | 69 | -- 收到推文的反应 70 | function goodFans:react() 71 | print("点赞,转发,打赏!" .. self.pub.article) 72 | end 73 | 74 | -- 路人 75 | local notFans = {} 76 | function notFans:new( o ) 77 | o = o or {} 78 | -- 关注的公众号 79 | o.pub = o.pub or {} 80 | setmetatable(o, self) 81 | self.__index = self 82 | 83 | return o 84 | end 85 | 86 | -- 收到推文的反应 87 | function notFans:react() 88 | print("没意思," .. self.pub.article) 89 | end 90 | 91 | 92 | local p = publish:new() 93 | local bf = blackFans:new({pub = p}) 94 | local gf = goodFans:new({pub = p}) 95 | local nf = notFans:new({pub = p}) 96 | 97 | p:beFollow(bf) 98 | p:beFollow(nf) 99 | p:beFollow(gf) 100 | 101 | p:wirte("核心对撞 | 伍壹玖原子对撞机") 102 | p:sendMsg() 103 | print('---------') 104 | p:wirte("核心对撞 | 伍壹玖原子对撞机金色天际线") 105 | p:sendMsg() 106 | -------------------------------------------------------------------------------- /decorator/decorator.lua: -------------------------------------------------------------------------------- 1 | require("oo") 2 | 3 | -----------person--------------- 4 | local person = class() -- 人,也就是 component 5 | 6 | function person:ctor(name) 7 | self.name = name 8 | end 9 | 10 | -- 展示,也就是 component 的统一接口 11 | function person:show() 12 | print("my name is " .. self.name) 13 | end 14 | -----------person end--------------- 15 | 16 | 17 | -----------decorator--------------- 18 | local decorator = class(person) -- 装饰抽象类,继承自 person,给人穿衣服,等于添加职责 19 | 20 | function decorator:ctor() 21 | print("decorator") 22 | -- self.component = {} 23 | -- self.component.show = function ( self ) 24 | -- -- body 25 | -- print("decorator") 26 | -- end 27 | end 28 | 29 | -- 这个是关键的对象组合顺序逻辑 30 | -- 通过这个然每个 decorator 子类能执行 component 31 | function decorator:show() 32 | if self.component then 33 | self.component:show() 34 | end 35 | end 36 | 37 | -- component|person 38 | function decorator:setDecorate( component ) 39 | self.component = component 40 | end 41 | 42 | 43 | 44 | -----------decorator end--------------- 45 | 46 | -----------pant--------------- 47 | local pant = class(decorator) -- pant 裤子,继承自 decorator,具体的添加职责 -- 穿裤子 48 | 49 | function pant:ctor() 50 | print("pant") 51 | end 52 | 53 | function pant:show( ... ) 54 | self:addPant() 55 | -- print(self.name) 56 | -- self.super:show() 57 | -- pant.super.show(self) 58 | end 59 | 60 | 61 | function pant:addPant() 62 | print("add a pant") 63 | end 64 | -----------pant end--------------- 65 | 66 | -----------shirt--------------- 67 | local shirt = class(decorator) 68 | 69 | function shirt:ctor() 70 | -- body 71 | print("shirt") 72 | end 73 | 74 | function shirt:show( ... ) 75 | -- body 76 | self:addShirt() 77 | -- print(self.name) 78 | 79 | -- 由于类的实现问题,不能实现 80 | -- shirt.super.show(self) 81 | end 82 | 83 | function shirt:addShirt( ... ) 84 | -- body 85 | print("add a shirt") 86 | end 87 | 88 | -----------shirt end--------------- 89 | 90 | local zyt = person:new("zyt") 91 | -- local de = decorator:new() 92 | local s = shirt:new() 93 | -- s:show() 94 | -- zyt:show() 95 | local p = pant:new() 96 | -- p:show() 97 | -- s:show() 98 | s:setDecorate(zyt) 99 | p:setDecorate(s) 100 | p:show() 101 | 102 | -------------------------------------------------------------------------------- /memento/memento.lua: -------------------------------------------------------------------------------- 1 | --------------------memento------------------- 2 | local memento = {} 3 | 4 | function memento.new(self, opt) 5 | opt = opt or {} 6 | 7 | -- 生命值 8 | opt.hp = opt.hp or 100 9 | -- 魔法值 10 | opt.mp = opt.mp or 100 11 | -- 经验值 12 | opt.exp = opt.exp or 0 13 | 14 | self.__index = self 15 | setmetatable(opt, self) 16 | return opt 17 | end 18 | 19 | --------------------memento end------------------- 20 | 21 | 22 | --------------------role------------------- 23 | local role = {} 24 | 25 | function role.new(self, opt) 26 | opt = opt or {} 27 | 28 | -- 生命值 29 | opt.hp = opt.hp or 100 30 | -- 魔法值 31 | opt.mp = opt.mp or 100 32 | -- 经验值 33 | opt.exp = opt.exp or 0 34 | 35 | self.__index = self 36 | setmetatable(opt, self) 37 | return opt 38 | end 39 | 40 | -- 用于信息回档 41 | -- menento 备忘录对象 42 | function role:recover(memento) 43 | self.hp = memento.hp 44 | self.mp = memento.mp 45 | self.exp = memento.exp 46 | end 47 | 48 | -- 生成一个备忘录用于部分数据备份 49 | function role:createMemento() 50 | return memento:new({ hp = self.hp, mp = self.mp, exp = self.exp}) 51 | end 52 | 53 | function role.fight(self) 54 | self.hp = 0 55 | self.mp = 0 56 | self.exp = 0 57 | end 58 | 59 | function role:show() 60 | print(self.hp) 61 | print(self.mp) 62 | print(self.exp) 63 | end 64 | 65 | --------------------role end------------------- 66 | 67 | --------------------caretaker------------------- 68 | local taker = {} 69 | function taker:new(opt) 70 | opt = opt or {} 71 | self.__index = self 72 | return setmetatable(opt, self) 73 | end 74 | 75 | function taker:take(memento) 76 | self.menento = menento 77 | end 78 | 79 | function taker:getMemento() 80 | return self.menento 81 | end 82 | 83 | 84 | 85 | 86 | --------------------caretaker end------------------- 87 | 88 | 89 | 90 | -- 实际调用 91 | 92 | -- 默认生命,魔法各100,经验为0 93 | local r = role:new() 94 | -- 备份当前状态 95 | -- 并且对调用者屏蔽了实现细节 96 | local m = role:createMemento() 97 | local c = taker:new() 98 | c:take(m) 99 | 100 | print("fight before") 101 | r:show() 102 | 103 | r:fight() 104 | print("fight done") 105 | r:show() 106 | 107 | 108 | -- 回档操作 109 | r:recover(c:getMemento()) 110 | print("recover") 111 | r:show() 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /facade/facade.lua: -------------------------------------------------------------------------------- 1 | 2 | -- 数据层下的数据库模块 3 | local data = {} 4 | 5 | function data:new( o ) 6 | o = o or {} 7 | 8 | setmetatable(o, self) 9 | self.__index = self 10 | 11 | return o 12 | end 13 | 14 | -- 设置数据库 mysql mongo .. 15 | function data:setDatabase(db) 16 | self.db = db 17 | print("set " .. db) 18 | end 19 | 20 | -- 连接数据库 21 | function data:connectDb( info ) 22 | -- body 23 | -- 在这里连接数据库会根据连接的数据库不同而不同,这里应该是要有进一步抽象,但是本次例子中忽略。 24 | print("connect to " .. self.db .. " to " .. info) 25 | end 26 | 27 | function data:exe( query ) 28 | -- body 29 | -- 这里执行数据库语句也是会有所不同,但是本次例子忽略 30 | print(self.db .. "执行 " .. query) 31 | end 32 | 33 | -- 数据层下的 log 日志系统模块 34 | local log = {} 35 | function log:new( o ) 36 | o = o or {} 37 | 38 | setmetatable(o, self) 39 | self.__index = self 40 | 41 | return o 42 | end 43 | 44 | function log:locate( path ) 45 | -- body 46 | self.path = path 47 | print("设置日志输出位置 " .. path) 48 | end 49 | 50 | function log:writeToFile( info ) 51 | print("将 " .. info .. " 写入日志文件") 52 | end 53 | 54 | function log:setLevel( lev ) 55 | print("等级为 " .. lev) 56 | end 57 | 58 | 59 | -- facade 外观层 60 | local facade = {} 61 | 62 | function facade:new( o ) 63 | o = o or {} 64 | 65 | setmetatable(o, self) 66 | self.__index = self 67 | 68 | return o 69 | end 70 | 71 | -- 随着子系统的增加或者拓展,一些逻辑需要的执行方法会越来越复杂,如果把这些逻辑放到业务层,增加了开发和阅读难度 72 | function facade:init() 73 | -- 数据层 数据库模块 74 | self.data = data:new() 75 | self.data:setDatabase("msyql") 76 | self.data:connectDb("12.12.12.12") 77 | 78 | -- 数据层 日志模块 79 | self.log = log:new() 80 | self.log:locate("./") 81 | self.log:setLevel("warning") 82 | 83 | end 84 | 85 | -- 更新对应表 86 | function facade:update( tbl ) 87 | self.data:exe("update ...") 88 | self.log:writeToFile("update " .. tbl) 89 | end 90 | 91 | -- 插入对应表 92 | function facade:insert( tbl ) 93 | self.data:exe("insert ...") 94 | self.log:writeToFile("insert " .. tbl) 95 | end 96 | 97 | -- 业务层 98 | local ser = {} 99 | 100 | function ser:new( o ) 101 | o = o or {} 102 | 103 | setmetatable(o, self) 104 | self.__index = self 105 | 106 | return o 107 | end 108 | 109 | function ser:init() 110 | self.facade = facade:new() 111 | self.facade:init() 112 | end 113 | 114 | function ser:setUser() 115 | self.facade:insert("tbl_user") 116 | end 117 | 118 | function ser:chgUser() 119 | self.facade:update("tbl_user") 120 | end 121 | 122 | 123 | -- 实际调用 124 | local s = ser:new() 125 | print("-----init") 126 | ser:init() 127 | 128 | print("-----start") 129 | ser:setUser() -------------------------------------------------------------------------------- /iterator/iterator.lua: -------------------------------------------------------------------------------- 1 | ----------iterator---------- 2 | -- 3 | local iterator = {} --迭代器抽象类 4 | 5 | 6 | function iterator:new(opt) 7 | opt = opt or {} 8 | 9 | --指针,指向遍历到的当前节点 10 | opt.count = opt.count or 0 11 | 12 | self.__index = self 13 | setmetatable(opt, self) 14 | return opt 15 | end 16 | 17 | -- 迭代器返回元素第一个 18 | function iterator:first() 19 | end 20 | 21 | -- 迭代器返回下一个元素 22 | function iterator:nextItem() 23 | end 24 | 25 | function iterator:isDone() 26 | end 27 | ----------iterator end---------- 28 | 29 | 30 | -----------aggregate--------- 31 | local aggregate = {} -- 聚集对象抽象类 32 | function aggregate.new(self, opt) 33 | opt = opt or {} 34 | 35 | self.__index = self 36 | setmetatable(opt, self) 37 | return opt 38 | end 39 | 40 | -- 返回一个迭代器 41 | function aggregate:createIterator() 42 | end 43 | 44 | -----------aggregate end--------- 45 | 46 | 47 | 48 | ---------乘务员---------- 49 | local ticker = iterator:new() 50 | 51 | function ticker:new(opt) 52 | opt = opt or {} 53 | 54 | --指针,指向遍历到的当前节点 55 | opt.count = opt.count or 0 56 | 57 | -- 将某时刻的bus聚集对象保存 58 | opt.bus = opt.bus or {} 59 | 60 | self.__index = self 61 | setmetatable(opt, self) 62 | return opt 63 | end 64 | 65 | -- 迭代器返回元素第一个 66 | function ticker:first() 67 | return self.bus.items[1] 68 | end 69 | 70 | -- 迭代器返回下一个元素 71 | function ticker:nextItem() 72 | if not self:isDone() then 73 | self.count = self.count + 1 74 | 75 | -- 这里可以就返回一个对象。或者对象的数据域 76 | -- 为了不暴露太多,就在内部将数据域返回 77 | return self.bus.items[self.count]["name"] 78 | end 79 | end 80 | 81 | function ticker:isDone() 82 | if self.count >= #self.bus.items then 83 | return true 84 | else 85 | return false 86 | end 87 | end 88 | ---------乘务员 end---------- 89 | 90 | ---------bus---------- 91 | -- 公交车聚集对象 92 | local bus = aggregate:new() 93 | 94 | function bus:new(opt) 95 | opt = opt or {} 96 | 97 | -- 乘客 98 | opt.items = opt.items or {} 99 | 100 | self.__index = self 101 | setmetatable(opt, self) 102 | return opt 103 | end 104 | 105 | function bus:createIterator() 106 | return ticker:new({ bus = self }) 107 | end 108 | ---------bus end---------- 109 | 110 | -------main------- 111 | local items = { 112 | [1] = { name = "zyt" }, 113 | [2] = { name = "zjt" }, 114 | [3] = { name = "zt" }, 115 | } 116 | 117 | local b = bus:new( { items = items } ) 118 | local tic = b:createIterator() 119 | print(b.items[2].name) 120 | print(#b.items) 121 | 122 | print(tic:nextItem() .. "买票吧!") 123 | print(tic:nextItem() .. "买票吧!") 124 | print(tic:nextItem() .. "买票吧!") 125 | 126 | -------------------------------------------------------------------------------- /composite/composite.lua: -------------------------------------------------------------------------------- 1 | ---------component------- 2 | -- component 节点类 3 | local component = {} 4 | 5 | function component.new(self, opt) 6 | opt = opt or {} 7 | opt.name = opt.name or "" 8 | opt.children = opt.children or {} 9 | 10 | self.__index = self 11 | setmetatable(opt, self) 12 | return opt 13 | end 14 | 15 | -- 为此节点添加子节点 16 | function component:add(node) 17 | end 18 | 19 | -- 遍历结构 20 | function component:display(depth) 21 | -- for _, v in ipairs(self.children) do 22 | -- v:display() 23 | -- end 24 | end 25 | 26 | -- 定义好的一致性方法 27 | function component:oneTask() 28 | end 29 | 30 | 31 | -- 为此节点删除一个节点 32 | -- function component:remove(node) 33 | -- table.insert(self.children, node) 34 | -- end 35 | 36 | 37 | ---------component end------- 38 | 39 | ---------leaf------- 40 | -- 叶子节点 41 | local leaf = component:new() 42 | 43 | -- 叶子节点不存在添加子节点 44 | function leaf:add(node) 45 | end 46 | 47 | 48 | function leaf:display(depth) 49 | local text = "" 50 | 51 | for i = 1, depth do 52 | text = text .. "--" 53 | end 54 | print(text .. self.name) 55 | end 56 | 57 | 58 | -- 叶子节点都是单模块,单独卖出 59 | function leaf:oneTask() 60 | print(self.name .. "is single selled") 61 | end 62 | 63 | ---------leaf end------- 64 | 65 | ---------composite------- 66 | local composite = component:new() 67 | 68 | function composite:add(node) 69 | table.insert(self.children, node) 70 | end 71 | 72 | function composite:display(depth) 73 | local text = "" 74 | 75 | for i = 1, depth do 76 | text = text .. "--" 77 | end 78 | print(text .. self.name) 79 | 80 | for _, v in ipairs(self.children) do 81 | -- print("--") 82 | v:display(depth + 1) 83 | end 84 | end 85 | 86 | -- 非叶子节点都是多模块组合,整体卖出 87 | function composite:oneTask() 88 | print(self.name .. "is whole selled") 89 | end 90 | 91 | 92 | 93 | ---------composite end------- 94 | 95 | ---------单独卖------- 96 | local single = leaf:new() 97 | 98 | function single:oneTask() 99 | print(self.name .. "is single selled") 100 | -- for _, v in ipairs(self.children) do 101 | -- v:oneTask() 102 | -- end 103 | end 104 | ---------单独卖 end------- 105 | 106 | ---------整体卖------- 107 | local whole = composite:new() 108 | 109 | function whole:oneTask() 110 | print(self.name .. "is whole selled") 111 | 112 | for _, v in ipairs(self.children) do 113 | v:oneTask() 114 | end 115 | end 116 | ---------整体卖 end------- 117 | 118 | ---main-- 119 | 120 | local computer = whole:new({ name = "computer" }) 121 | 122 | local screen = single:new({ name = "screen" }) 123 | local zhuji = whole:new({ name = "zhuji" }) 124 | computer:add(screen) 125 | computer:add(zhuji) 126 | 127 | local cpu = single:new({ name = "cpu" }) 128 | local cache = single:new({ name = "cache" }) 129 | zhuji:add(cpu) 130 | zhuji:add(cache) 131 | 132 | 133 | computer:display(0) 134 | computer:oneTask() 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | --------------------------------------------------------------------------------