|
 
- 帖子
- 666
- 积分
- 1081
- 声望
- 1071
- 性别
- 男
- 来自
- 暗影之月,玛瑟里顿
|
1#
发表于 2007-7-5 20:33
| 只看该作者
[插件] Eva Framework 编程最佳实践
作者: simonw From CWDG 转载请注明出处.
Eva Framework 可以把他理解为WoW插件开发中的MVC框架或者更简单的说使用了Façade模式统一了一系列触发行为与执行过程的聚合物. 那么究竟统一了哪些呢?
程序的触发行为在WoW中总共分为5种(目前4,5未实现)
1.系统事件
2.窗体事件
3.Slashcommand
4.按键绑定
5.宏
面对各种不同的触发方式我们在编写插件的时候往往很容易与业务模块混杂在一起, 这部分称之为UI控制逻辑. 混杂的结果就会造成代码不易阅读不易维护和复用. Eva Framework实现了一个controller来负责分发各种不同的请求, 这样达到使业务模块与UI部分分离从而既能够达到快速开发的目的又能使你的代码复用性提高很多.
在Eva Framework包含一个统一的命令执行引擎, 从Façade接收到的请求被分发到不同的Handler之后最后都统一交给命令执行引擎来执行, 这个命令执行引擎最大化的利用了WoW的执行能力从而可以在非安全相关的动作中实现复杂的延时,挂起,甚至多线程.
注: 多线程, 这里并不是只传统意义上的多线程, 他同时包含多进程的概念. 具体行为是, 他们并不是共同处理一项任务, 而是并行处理多个同样的任务, 但他们共享一个数据空间, 自己保存自己独立的上下文, 互相之间可以通讯.
为了有个更未感性的认识, 看看如果具体开始. 这里以ShortStory为例, 这是一个根据不同的用户文字输入来实现不同的文字内容点播的插件, 除去注释只有不到200行的代码, 也许你不敢相信如此少的代码竟能实现如此强大的功能(夸大了,呵呵, 别扁我, 如同SUN和MS都在夸大自己平台下的PetShop).
文件结构:
ShortStory.toc
ShortStory.lua
ShortStoryEntry.lua
ShortStoryConfig.lua
层次化结构的插件开发, 由高至底.
1.UI层(这个示例中没有, 一般是XML界面)
2.UI控制逻辑层
3.Service层
4.业务层
这里只有上层依赖下层, 切忌不同层次间互相引用, 这样造成的耦合会带来很多困扰.
提示: 引入行如命名空间的方式, 保持尽量少的全局变量的声明. ShortStory = {
Scheduler = {}
} UI控制逻辑层
在ShortStoryEntry.lua中,响应各种请求,这里就是各种block配置对象,他们负责监听来自UI的请求后传递给相应的Service层对应函数.
--创建并初始化插件
local ShortStoryAddon = EVA.Addon:New()
--设置插件相关描述
ShortStoryAddon.Name = "ShortStory"
ShortStoryAddon.Version = "1.3"
ShortStoryAddon.Description = "auto play story. By simonw. URL[http://wiki.cwowaddon.com/]"
--将插件添加到插件注册表中
EVA.AddonRegistry:Add(ShortStoryAddon)
local Scheduler = ShortStory.Scheduler
--创建功能集
local initBlock = {
Name = "Init Block",
Description = "Init story",
RequestTypes = {"Event"},
Events = {"PLAYER_LOGIN"},
Enabled = 1,
Commands = {
{Description = "Init story", Function = Scheduler.Init},
}
}
local playBlock = {
Name = "Play Block",
Description = "Display story",
RequestTypes = {"EventChatCommand"},
Events = {"CHAT_MSG_WHISPER","CHAT_MSG_RAID","CHAT_MSG_SAY","CHAT_MSG_PARTY"},
Permission = {AllowList = {"&Player", "&Friend", "&Everyone"}},
Enabled = 1,
Commands = {
ChatCommand = "list",
{Description = "get process", Function = function(context) ShortStory.Context = context end},
{Description = "show start info", Function = Scheduler.PlayTip},
{Description = "show story content", Function = Scheduler.PlayStory, Timer = {Interval = 2, Times = -1}},
}
}
.......................
--将功能集合添加到插件中
ShortStoryAddon:Add(EVA.Block:New(initBlock))
ShortStoryAddon:Add(EVA.Block:New(playBlock))
ShortStoryAddon:Add(EVA.Block:New(stopBlock))
ShortStoryAddon:Add(EVA.Block:New(listBlock))
Service层
ShortStory.lua中, Scheduler部分,负责处理来自UI控制逻辑层的请求参数及流程上下文并传入业务对象,他只是简单的包装了业务逻辑需要为用户公开的接口部分, 在这里不应包含具体的业务逻辑.
--从ShortStory.Words中获取故事标题,插件数据初始化行为
function Scheduler.Init()
ShortStory:SetTitles()
end
...................
--打印故事内容
function Scheduler.PlayStory(context)
if (not context.itemIndex) then
context.itemIndex = 1
end
local result = ShortStory:PlayStory(tonumber(context.Event_ChatArgs[1]), context.itemIndex)
if (result) then
context.itemIndex = context.itemIndex + 1
end
end
--故事停止
function Scheduler.PlayStop(context)
ShortStory:PlayStop()
end 业务层
ShortStory.lua中, ShortStory业务模型本身,只包含业务逻辑,不应包含任何与请求有关代码.这样你能获得更容易维护和复用的Buff
function ShortStory:PlayList()
for index, title in ipairs(self.Titles) do
self:Print(self.Formats["Title"], index, title)
end
end
function ShortStory:PlayTip(index, sender)
if (index) then
self:Print(self.Formats["Tip"], sender, index)
end
end
.............
function ShortStory:SetTitles()
self.Titles = {}
for index, article in ipairs(self.Words) do
self.Titles[index] = self:GetArticleItem(article, 1)
end
end 最后你需要注意toc中的载入顺序. 欢迎各位提出各种问题,疑问,建议....无论好坏. 多谢捧场.
EVA Framework相关资料:
意见征集 编程最佳实践 下载 文档 |
|