QFramework 基于 MVC 的开发模式
所以我们先从最熟知的 MVC 架构开始着手 QFramework 的学习。
我们先做一个非常简单的计数器应用。
首先我们使用 UGUI 创建一个最简单的界面,如下图所示:
场景结构如下所示:
复制完之后,我们创建一个脚本叫做 CounterAppController,代码如下:
using UnityEngine;
using UnityEngine.UI;
namespace QFramework.Example
{
// Controller
public class CounterAppController : MonoBehaviour
{
// View
private Button mBtnAdd;
private Button mBtnSub;
private Text mCountText;
// Model
private int mCount = 0;
void Start()
{
// View 组件获取
mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>();
mBtnSub = transform.Find("BtnSub").GetComponent<Button>();
mCountText = transform.Find("CountText").GetComponent<Text>();
// 监听输入
mBtnAdd.onClick.AddListener(() =>
{
// 交互逻辑
mCount++;
// 表现逻辑
UpdateView();
});
mBtnSub.onClick.AddListener(() =>
{
// 交互逻辑
mCount--;
// 表现逻辑
UpdateView();
});
UpdateView();
}
void UpdateView()
{
mCountText.text = mCount.ToString();
}
}
}
代码很简单,这是一个非常简易的 MVC 的实现。
我们将此脚本挂在 Canvas 节点上,运行 Unity 结果如下:
非常简单。
此时我们还没有导入我们的 QFramework,不着急,我们先看看代码中所介绍的概念。
首先是 Model、View、Controller
Model 的代码如下:
// Model
private int mCount = 0;
非常简单,只有一个成员变量,但是在这里它其实并不算是一个 Model,他只是要在 View 中显示的一个数据而已,具体为什么不是 Model 我们在后边再说。
View 的代码如下:
// View
private Button mBtnAdd;
private Button mBtnSub;
private Text mCountText;
View 的代码也很简单,View 在 QFramework 的 MVC 定义里就是提供关键组件的引用,比如这三个组件是要在 Controller 代码里要用到的。而其他的例如 Canvas Scaler 等这些组件目前 Controller 不需要,所以就不用声明。
Controller 的代码,如下:
void Start()
{
...
// 监听输入
mBtnAdd.onClick.AddListener(() =>
{
// 交互逻辑
mCount++;
// 表现逻辑
UpdateView();
});
mBtnSub.onClick.AddListener(() =>
{
// 交互逻辑
mCount--;
// 表现逻辑
UpdateView();
});
UpdateView();
}
void UpdateView()
{
mCountText.text = mCount.ToString();
}
以上就是 Controller 的代码。
好了,我们回头再看下完整代码。
using UnityEngine;
using UnityEngine.UI;
namespace QFramework.Example
{
// Controller
public class CounterAppController : MonoBehaviour
{
// View
private Button mBtnAdd;
private Button mBtnSub;
private Text mCountText;
// Model
private int mCount = 0;
void Start()
{
// View 组件获取
mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>();
mBtnSub = transform.Find("BtnSub").GetComponent<Button>();
mCountText = transform.Find("CountText").GetComponent<Text>();
// 监听输入
mBtnAdd.onClick.AddListener(() =>
{
// 交互逻辑
mCount++;
// 表现逻辑
UpdateView();
});
mBtnSub.onClick.AddListener(() =>
{
// 交互逻辑
mCount--;
// 表现逻辑
UpdateView();
});
UpdateView();
}
void UpdateView()
{
mCountText.text = mCount.ToString();
}
}
}
目前像计数器这样的逻辑,以上的代码完全没有问题。
但是我们要用发展的眼光看待问题。
假如这是一个初创项目,那么接下来很有可能需要添加大量的业务逻辑。
其中很有可能让 mCount 在多个 Controller 中使用,甚至需要针对 mCount 这个数据写一些其他逻辑,比如增加 mCount 则增加 5 个分数,或者 mCount 需要存储等,总之 mCount 在未来可能会发展成一个需要共享的数据,而 mCount 目前只属于 CounterAppController,显然在未来这是不够用的。
我们就需要让 mCount 成员变量变成一个共享的数据,最快的做法是吧 mCount 变量变成静态变量或者单例,但是这样虽然写起来很快,但是在后期维护额度时候会产生很多的问题。
而 QFramework 架构提供了 Model 的概念。
我们来使用一下。
我们先导入 QFramework 架构。
导入 QFramework 的方式非常简单,只需要复制 QFramework.cs 的代码到 Unity 工程中即可。
QFramework.cs 地址:
- Gitee: https://gitee.com/liangxiegame/QFramework/blob/master/QFramework.cs
- Github: https://github.com/liangxiegame/QFramework/blob/master/QFramework.cs
导入之后,我们将 CounterAppController 的代码改成如下:
using UnityEngine;
using UnityEngine.UI;
namespace QFramework.Example
{
// 1. 定义一个 Model 对象
public class CounterAppModel : AbstractModel
{
public int Count;
protected override void OnInit()
{
Count = 0;
}
}
// 2.定义一个架构(提供 MVC、分层、模块管理等)
public class CounterApp : Architecture<CounterApp>
{
protected override void Init()
{
// 注册 Model
this.RegisterModel(new CounterAppModel());
}
}
// Controller
public class CounterAppController : MonoBehaviour , IController /* 3.实现 IController 接口 */
{
// View
private Button mBtnAdd;
private Button mBtnSub;
private Text mCountText;
// 4. Model
private CounterAppModel mModel;
void Start()
{
// 5. 获取模型
mModel = this.GetModel<CounterAppModel>();
// View 组件获取
mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>();
mBtnSub = transform.Find("BtnSub").GetComponent<Button>();
mCountText = transform.Find("CountText").GetComponent<Text>();
// 监听输入
mBtnAdd.onClick.AddListener(() =>
{
// 6. 交互逻辑
mModel.Count++;
// 表现逻辑
UpdateView();
});
mBtnSub.onClick.AddListener(() =>
{
// 7. 交互逻辑
mModel.Count--;
// 表现逻辑
UpdateView();
});
UpdateView();
}
void UpdateView()
{
mCountText.text = mModel.Count.ToString();
}
// 3.指定架构
public IArchitecture GetArchitecture()
{
return CounterApp.Interface;
}
private void OnDestroy()
{
// 8. 将 Model 设置为空
mModel = null;
}
}
}
好了,代码引入了两个新的概念,一个是 Architecture,另一个是 Model。
Architecture 用于管理模块,或者说 Architecture 提供一整套架构的解决方案,而模块管理和提供 MVC 只是其功能的一小部分。
我们运行一下 Unity 结果如下:
运行正确。
好了,我们上手了 QFramework 提供的 MVC 架构。
这里要注意一点,Model 的引入是为了解决数据共享的问题,而不是说单只是为了让数据和表现分离,这一点是非常重要的一点。
数据共享分两种:空间上的共享和时间上的共享。
空间的共享很简单,就是多个点的代码需要访问 Model 里的数据。
时间上的共享就是存储功能,将上一次关闭 App 之前的数据存储到一个文件里,这次打开时获得上次关闭 App 之前的数据。
虽然我们上手了 MVC,但是这样的 MVC 还有很多问题,我们下一篇继续解决。
更多内容
- 转载请注明地址:liangxiegame.com (首发) 微信公众号:凉鞋的笔记
- QFramework 主页:qframework.cn
- QFramework 交流群: 623597263
- QFramework Github 地址: https://github.com/liangxiegame/qframework
- QFramework Gitee 地址:https://gitee.com/liangxiegame/QFramework
- GamePix 独立游戏学院 & Unity 进阶小班地址:https://www.gamepixedu.com/