游戏开发中的前端解耦设计
来源:互联网 发布:淘宝开店客服电话 编辑:程序博客网 时间:2024/06/05 17:30
软件开发中最基础的设计架构就是整个项目的解耦问题。设计人员会根据已有的设计模式结合自身经验设计一套适合当前系统状态和团队状态的解耦架构,以保证在多人开发中的协调性与项目的可扩展性、易读性、兼容性等问题。本章将通过讲解几种设计模式最终组合出一套完整的前端解耦架构。
外观模式(Facade)
Facade模式为子系统中的各类(或结构与方法)提供一个简明一致的界面,隐藏子系统的复杂性,使子系统更加容易使用。它是为子系统中的一组接口所提供的一个一致的界面。结构图如下:
上图已经简单的描述了Facade模式的结构概念。直白些说就是,通过主系统去调用子系统模块的方法。实际上这个观念有点类似于适配器。使用Facade模式可以为复杂的子系统一共一个简单的视图,并且提高了子系统的独立性,这样在感官上更具备层次化,设计结构清晰明了。
观察者模式(Observer)
观察者模式有时也被称作发布/订阅模式,定义一种一对多的依赖关系,使一个对象发送消息后,修改多个依赖对象的状态。观察者模式一种常见的实现方式为注册-通知-撤销。它其中包含了三个对象:
观察者:被通知的对象,它需要事先注册对应消息。
通知者:发生改变的对象,当状态发生改变时通知所有依赖它的观察者更新。
消息:消息标识观察者感兴趣的内容。
如图所示,这是一个简单的观察者模式模型。Observer1、Observer2、Observer3分别注册入通知者Notifier中,这样我们就可以发送状态消息给观察者使用了。
调停者模式(Mediator pattern)
调停者模式是对象的行为模式。调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显引用。从而使它们可以较松散地耦合。当这些对象中的某些对象之间的相互作用发生改变时,不会立即影响到其他的一些对象之间的相互作用。从而保证这些相互作用可以彼此独立地变化。
在前端设计中,调停者被用于组织界面显组件。简单来说,我有一个现实界面其中包含了3个按钮一个图片和一行文字,那么我可以使用调整者把这几种组件按照我希望的想法组织起来,并接收我可能需要的显示数据和用户交互响应数据。
如图我们用调停者模式将多个显示对象封装到一个调停者对象中,这样可以集中的管理各个显示对象之间的交互以及关联。
命令模式(Command)
命令模式实际上就是把一个请求或者操作封装到一个对象中,使我们可以通过命令区分调度。命令模式最大的特点就是新的命令可以很容易地加入到系统中,使我们在实际开发中更容易的扩展某个模块中的功能,或者重新组合某个模块的功能调度。
一套前端解耦架构的实现
相信大家在日常开发中最常听见的一种架构思路就是MVC架构。它是讲显示对象/逻辑控制/数据分拆开来的一种设计模式。而接下来我将根据以上我所提到的设计模式实现一组我认为比较适合前端开发中使用的MVC架构。
首先我们先要实现一个观察者模式,它提供了注册,移除注册,以及消息发送功能。代码如下:
-- 通知者local Notifier = class("Notifier")function Notifier:ctor() self.container = {}end-- 添加一个观察者function Notifier:addObserver(mediator) local array = mediator:getListNotifications() for key, var in ipairs(array) do if self.container[var] == nil then self.container[var] = {} end table.insert(self.container[var],mediator) endend-- 删除一个观察者function Notifier:removeObserver(mediator) local array = mediator:getListNotifications() for key, var in ipairs(array) do if self.container[var] ~= nil then local j = 1 local len = #self.container[var] for i=1,len do local observer = self.container[var][j] if observer == mediator then table.remove(self.container[var],j) else j = j + 1 end end end endend-- 发送消息function Notifier:notiftyObservers(notifierName,body,type) local observers = self.container[notifierName] if observers == nil then return end local notifitionBody = {name=notifierName,body=body,type=type} for key, var in ipairs(observers) do var:handleNotification(notifitionBody) endendreturn Notifier
这样我们可以通过通知者提供的addObserver、removeObserver、notiftyObservers来实现我们初步的消息监听功能。
接下来我们实现一个Command的基类,用于描述我们的命令模式的结构。
Command = class("Command")Command.__index = Commandfunction Command:ctor()endfunction Command:execute(value)end
在使用中我们只要继承Command类,然后重新实现execute方法,解析该命令控制器中所对应的命令操作。
我们再来实现Mediator的基类,用于描述协调者模型定义。
Mediator = class("Mediator")Mediator.__index = Mediatorfunction Mediator:ctor()endfunction Mediator:getName() return nilendfunction Mediator:getListNotifications() return {}endfunction Mediator:removeMediator()end function Mediator:handleNotification(value)end
Mediator类提供了几种必要定义接口。
Mediator:getName()
方法表示当前定义模块的唯一标识名。
Mediator:getListNotifications()
方法表示当前定义模块所关注的消息状态。
Mediator:removeMediator()
方法在当前模块移除时会被调用触发。
Mediator:handleNotification()
方法在当前模块所关注消息被出发时调用。
最后我们来实现Facade类的功能,代码如下:
-- 外观模式require("chapter_2.Command")require("chapter_2.Mediator")Facade = { commandMap = {}, mediatorMap = {}, notifierMap = {}, notifier = require("chapter_2.Notifier").new()}function Facade.registerCommand(notifierName,command) if self.commandMap[notifierName] == nil then self.commandMap[notifierName] = command.new() endendfunction Facade.registerMediator(mediator) if self.mediatorMap[mediator:getName()] == nil then self.mediatorMap[mediator:getName()] = mediator self.notifier:addObserver(mediator) endendfunction Facade.removeCommand(notifierName) self.commandMap[notifierName] = nilendfunction Facade.removeMediator(notifierName) local mediator = self.mediatorMap[notifierName] if mediator ~= nil then self.notifier:removeObserver(mediator) mediator:removeMediator() end self.mediatorMap[notifierName] = nilendfunction Facade.hasCommand(notifierName) if self.commandMap[notifierName] ~= nil then return true end return falseendfunction Facade.hasMediator(notifierName) if self.mediatorMap[notifierName] ~= nil then return true end return falseendfunction Facade.sendNotification(notifierName,body,type) if self.commandMap[notifierName] ~= nil then local command = self.commandMap[notifierName] local notifitionBody = {name=notifierName,body=body,type=type} command:execute(notifitionBody) return end self.notifier:handleNotification(notifierName,body,type)end
Facade类将是一个全局单例,在上边我没有介绍单例模式,由于他很常见我就不再熬述。简单说明下Facade中的方法含义。
Facade.registerCommand()
方法表示用于注册Command实例。
Facade.registerMediator()
方法表示用于注册Mediator实例。
Facade.removeCommand()
方法表示用于移除Command实例。
Facade.removeMediator()
方法表示用于移除Mediator实例。
Facade.hasCommand()
方法表示用于检测Command实例是否注册。
Facade.hasMediator()
方法表示用于检测Mediator实例是否注册。
Facade.sendNotification()
方法表示用于命令与消息的发送。
这样一套完整的MVC解耦架构就实现完成了。其中Mediator用于控制显示层对象,Command用于组合Mediator所需要的数据结构,Facade用于事件的调度和Mediator、Command对象实力的管理。说到这里大家要疑问Module层哪里去了,实际上Module层并不和当前架构有直接关联,只要在我们具体的业务逻辑开发中实现一套数据管类器以及对应的各种数据结构模型就可以了。
以上是一套完整的解耦架构实现,具体的使用我将在下一篇文章中详细介绍。
- 游戏开发中的前端解耦设计
- 游戏开发中的前端解耦设计(二)
- 网站前端开发设计中的SEO技巧
- 设计模式在游戏开发中的应用
- 游戏开发中的ECS设计模式初探
- HTML5游戏前端开发秘籍
- 游戏开发中的设计模式之一-Strategy模式
- J2ME游戏开发中的地图设计与绘制
- 设计模式在游戏开发中的应用之命令模式
- 设计模式在游戏开发中的应用之观察者模式
- 游戏开发中的系统设计:新手引导系统
- 游戏开发中的设计模式——总览
- 游戏开发中的设计模式——1.状态模式
- 游戏开发中的设计模式——2.外观模式
- 游戏设计中的心理学
- 游戏设计中的合作
- 游戏设计中的配置文件
- 游戏中的ai设计
- 学习和人生规划的四种境界
- java中的classloader
- 又是一篇感慨
- unity3d更新全书,转
- 算法与数据结构面试题(23)-将字符串转化为整形
- 游戏开发中的前端解耦设计
- C#编写通用数据库访问类
- 认识和分析日志文件 Linux
- GC如何知道对象没被引用(孤岛例子)
- UVA - 10499 The Land of Justice
- 对最近一段时间学习的总结
- 计算当前时间和⼀一个固定时间的差值
- 92SlidingDrawer控件介绍
- 视频下载工具“硕鼠”与遨游浏览器的比拼(图文)