文章目录
概述(注:非终版)
- View 通常是被动展示,Presenter 负责把 Model/System 的数据整理成界面需要的状态。
- 总结:Module + (MVP/MVC) + System(+ Proxy + EventBus / CommandBus)
- 功能模块:
- Module
- Model
- Passive View
- Presenter
- System
- Proxy
- EventBus / CommandBus
各层职责
Module
模块入口可以理解为:一个功能包的总入口,只做装配和生命周期管理。负责:
- 注册 Model。
- 注册 Presenter。
- 注册 System。
- 注册 Proxy。
- 注册 View。
- 注册模块事件。
- 初始化和销毁模块。
不负责:
- 不写复杂业务规则。
- 不直接处理大量 UI 刷新细节。
- 不堆协议回包里的业务计算。
Model
Model 不应该直接操作 UI,也不应该直接发起网络请求。主要保存模块数据和状态,负责:
- 保存服务器数据。
- 保存本地状态。
- 提供基础查询。
- 提供简单数据更新。
View
只负责展示和用户输入,负责:
- 显示列表。
- 显示文本、图标、红点。
- 播放动画。
- 派发按钮点击。
- 暴露界面刷新接口。
不负责:
- 不判断复杂业务规则。
- 不直接改 Model。
- 不直接发协议。
- 不直接访问其他模块的核心数据。
推荐做成 Passive View,也就是 View 尽量被动:
- Presenter 给什么数据,View 就展示什么数据。
- View 捕获到点击,只通知 Presenter。
Presenter
负责 UI 流程和界面协调(注意不要从名字而是从职责区分是不是Presenter):
- 监听 View 的点击。
- 从 Model 取数据。
- 调用 System 做业务判断。
- 调用 Proxy 发请求。
- 把数据整理成 View 需要的格式。
- 监听事件并刷新 View。
例如:
typescript
HeroPresenter.onClickLvUp()
-> HeroSystem.checkCanLvUp()
-> HeroProxy.reqLvUp()
Presenter 是 UI 业务的调度层。
System
负责业务规则,适合放在 System 的逻辑(System 不应该直接操作 View):
- 英雄升级条件判断。
- 战力计算。
- 红点判断。
- 功能开启判断。
- 奖励合并。
- 跨界面复用的业务逻辑。
- 条件表达式判断。等。
判断标准:
- 如果逻辑不依赖具体 UI,并且可能被多个地方复用,就放到 System。
Proxy
负责协议层:
- 发送协议。
- 接收回包。
- 把协议数据转换成 Model 可用的数据。
- 通知 Presenter 或 EventBus。
- Proxy 的作用是避免 Presenter 或 Module 里堆太多网络细节。
- 如果项目协议很简单,也可以先不拆 Proxy,把协议放在 Module 里。但中大型项目建议拆出来。
和战斗 ECS 的边界
- 业务 UI 和战斗 ECS 应该分开(目录结构分开)。
- 业务 UI 不直接操作 ECS 内部实体(通过清晰接口连接,比如门面模式)。
- 不要这样做:XxxView -> battleWorld.getEntity(id).getComponent(...)
为什么不在业务 UI 中使用 ECS
业务 UI 的主要问题不是高频实体遍历,而是:
- 界面状态管理。
- 数据刷新。
- 跨模块事件。
- 用户点击流程。
- 等等。以上这些不是 ECS 擅长的"批量处理实体组件"问题,而是业务流程问题。
命名建议
- Module
- Model
- View(Passive View
- Presenter
- System(Business System
- (+ Proxy + EventBus / CommandBus)
总结
- 管理业务和 UI 部分推荐:Feature Module + MVP + System
- 战斗部分推荐:ECS
- 两者通过 Facade、事件、结果数据进行通信,不要互相侵入内部实现。