见3https://blog.csdn.net/wangjiang Rong/article/details/107686954
3359 www.cn blogs.com/skynet/archive/2013/03/14/2958644.html
3359 blog.csdn.net/QQ _ 29579137/article/details/73692842
挪用了一些其他文章的流程图
PureMVC个人整理前言MVC与PureMVC设计模式一例模式(Singleton )外观模式(Facade )观察者模式(Observer )中间人模式(Mediator )代理模式(Proxy )命令模式) commetry )
最近负责项目UI框架部分的构建,调查了一些资料后,借鉴了其他项目的想法。 在这里整理一下,项目UI部分是用Lua写的,粘贴的相关代码也是Lua代码。 因为是边学习边写,所以命名规则是以项目标准命名的。 (
MVC和PureMVC目标:分离数据(模型)、视图组件(视图组件)和控制逻辑)。 程序的修改变得容易,提高了扩展性、灵活性和复用性。 高凝聚、低偶联,始终是追求的目标。 传统的MVC模型分离数据、视图组件和控制逻辑,但结合性较高。
PureMVC在MVC的基础上做了很多改进,通过组合多种设计模式的应用,降低了耦合性,便于使用,在扩展性、灵活性、复用性方面也有很好的表现
设计模式的单实例模式(Singleton )在PureMVC中,Model、View、Controller是三个单实例模式类,三者合称为核心层,实际上
外观模式(Facade )在开发过程中,需要在Contoller中获取View和Model对象,修改Mode,更新View,或者在View中获取Model,进行一些初始化或修改的操作PureMVC为模型、视图和控制器类提供外观类Faade,主要负责访问和通知模型、视图和控制器,也就是管理这三个类。 faade将这3者的界面统一对外提供,为了只与faade交往而使用流程
观察模式(Observer )也称为发送/订阅模式,使用PureMVC或观察模式)以完全解绑定并避免直接的函数调用。 在PureMVC中,Mediator、Proxy、Command之间的通信通过通知形式实现松散耦合。 Mediator、Proxy、Command都可以由通知者(发行者)调用sendNotification发送消息; Mediator、Command的观察者(订阅者)可以接收来自其他对象的通知。
在这里,你不需要在意Mediator、Proxy和Command是什么。 请注意,Mediator和Command既是通知者也是观察者,而Proxy又是通知者
Proxy=Model,Mediator=View,Command=Controller
所有通知者(发布者)都继承自通告程序类,因此具有发布通知的功能,通告程序使用Faade发布通知
从外观模式中可以看出,faade保存了View的参照,View在观察者模式中起到了管理员的作用,保存了所有的消息/主题、观察者的映射。 当Mediator/Command/Proxy发出通知时,faade将调用View的notifyObservers ()方法,遍历保存的映射关系,并通知所有符合条件的观察者
函数通告程序3360发送通告(通告名称,主体, type ) local facade=self : get facade (if facade )=nilthenfacade 3360 send notification name,body, type ) endendfunctionfacade :发送通知(notification name,body, type ) self : notify observers (notification.type type ) )结束函数: notify observers (notification ) if self.type
重写Command的Execute方法实现回调
p> function Controller:RegisterCommand(notificationName, commandClassRef) if(self.mCommandMap[notificationName] == nil) then self.mView:RegisterObserver(notificationName, Observer.New(self.ExecuteCommand, self)); end self.mCommandMap[notificationName] = commandClassRefend function Controller:ExecuteCommand(note) local commandClassRef = self.mCommandMap[note:GetName()] if(commandClassRef == nil) then return end local commandInstance = commandClassRef.New() commandInstance:InitializeNotifier(self.mMultitonKey) commandInstance:Execute(note)endMediator 中调用 View 的 RegisterMediator
通过复写Mediator的ListNotificationInterests方法实现回调
在PureMVC中,Mediator帮助我们创建或重用已有UI组件,而UI不用知道PureMVC框架相关的东西,UI仅用于显示数据、接收用户输入。Mediator是UI组件与框架的中介,它负责将来自PureMVC框架的消息转接到UI,并将UI的消息转发广播到PureMVC框架。这样通过Mediator解耦了UI与PureMVC框架元素(Proxy、Mediator、Command),而不用互相引用。
一个Mediator只与一个UI绑定(1对1),Mediator构造函数参数传递与之绑定的UI。通过façade的registerMediator方法注册Mediator,以接收PureMVC框架的通知
Mediator接收PureMVC传来的Notification,调用UI函数
接收UI派发的事件,转发Notification传回PureMVC框架
例如 当点击领取邮件按钮,EmailUI发送消息给EmailMediator传给PureMVC,(中间可能涉及服务器交互),之后PureMVC,需要更新背包内容就发送消息给BagMediator,BagMediator接收事件以后更新BagUI,Bag功能和Email功能并没有影响
代理模式(Proxy)在PureMVC中,Proxy帮助我们以更易于重用、修改对应用程序影响最小的方式暴露数据结构、接口给应用程序。Proxy可能只是简单的管理本地数据对象,以同步方式获取或修改数据;也可能是远程服务器数据,以异步方式操作数据,服务器数据返回之后以Notification方式告诉应用程序。
简单来说,Proxy对数据逻辑进行包装,只对外公布操作数据对象的API 例如EmailProxy负责接收来自服务器的邮件内容,当邮件更新时,EmailUI并不需要关心邮件数据是什么形式发来的,当EmailUI需要展示邮件内容,只需要调取EmailProxy公布的API(例如EmaliProxy.GetEmailList)即可,反之,当发送邮件时,EmailUI也不需要关注怎么发送,以什么样数据格式发给服务器,一切逻辑都由EmailProxy处理,这样极大程度实现了对一些处理逻辑的封装,降低了耦合。
命令模式(Command)命令模式是对命令的封装,把发出命令的责任和执行命令的责任分割开,委派给不同的对象。每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
在PureMVC中,命令用来检索、操作Proxy,或者与Mediator通信,或者执行其它命令。
例如:EmailMediator 接收到来自UI的sendEmail的消息,EmailMediator把消息传到SendEmailCommand, SendEmailCommand持有EmailProxy的引用,调用EmailProxy的SendEmail接口发送消息
一般是继承Facade类注册 开始事件,这里是 STARTUP, 然后继承Command 构造 StartUpCommand
这里可以参考网上一些完整样例。
通过StartUp开启
单模块通信
红色为直接调用,绿色为事件通信
Proxy只发送消息不接受消息,是通过Command直接调用的,原因是设计时Proxy要负责和服务器交互,再监听其他事件过于繁琐
多模块通信
黄色线也是可能存在的事件,因为观察者模式不需要关注消息的来源,只要订阅了相关消息就可以触发
例如EmailProxy接收到服务器消息更新时也需要更新BagUI就可以发送消息给BagMediator
或者EmailUI也可以购买物品可以发送消息给
EmailMediator转发给BagCommand调用BagProxy
因为都是消息机制,整个流程很长,而且Proxy中对数据进行操作后,发送Notification时,可能需要携带修改后的数据(可能是来自服务器的数据)。这个过程不仅通过次数多,而且带反馈数据的消息增加通信负担。另一方面要调试这个过程,我们只能在编译的时候找出一步一步的通信流程,才能跟踪调试。
因为游戏项目本身不需要过于解耦,UI部分不希望出现类爆炸的情况,在此基础上进行了一些修改
UI 和 Mediator 结合Mediator和UI之间的通信有点繁琐,可以让UI持有Mediator,这样UI可以通过持有的UIMediator 与PureMVC交互,并且接收到消息时,也可以直接调用自身UI函数,不再需要Mediator持有UI调用
function UIMediator:ListNotificationInterests() if(self.mViewComponent ~= nil) then local result = self.mViewComponent:ListNotificationInterests() return result end return {}end function UIMediator:HandleNotification(notification) if(self.mViewComponent ~= nil) then return self.mViewComponent:HandleNotification(notification) endendUI直接绑定一个公用的UIMediator通过UIMeditaor发送消息和PureMVC交互
Command中介多余数据相关部分已经被Proxy封装好,可以考虑不再需要通过Command转发,可以直接由UI(UIMediator)调用Proxy的接口以减少类的数量,Proxy之间的调用可以通过加一个全局注册事件触发
修改后交互过程UI 通过调用自身的成员变量UIMediator发送消息
并通过在UIMediator中注册的消息响应来自来自外部的消息
UI不再经过Command调用Proxy 而是直接调用Proxy