游戏开发中的前端解耦设计

来源:互联网 发布:淘宝开店客服电话 编辑:程序博客网 时间: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层并不和当前架构有直接关联,只要在我们具体的业务逻辑开发中实现一套数据管类器以及对应的各种数据结构模型就可以了。

以上是一套完整的解耦架构实现,具体的使用我将在下一篇文章中详细介绍。



0 0