什么是MVC:
模型-视图-控制器模式,也称为MVC模式(Model View Controller)。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。它把软件系统分为三个基本部分:
模型(Model):负责存储系统的中心数据。
视图(View):将信息显示给用户(可以定义多个视图)。
控制器(Controller):处理用户输入的信息。负责从视图读取数据,控制用户输入,并向模型发送数据,是应用程序中处理用户交互的部分。负责管理与用户交互交互控制。
视图和控制器共同构成了用户接口。
且每个视图都有一个相关的控制器组件。控制器接受输入,通常作为将鼠标移动、鼠标按钮的活动或键盘输入编码的时间。时间被翻译成模型或试图的服务器请求。用户仅仅通过控制器与系统交互。
QFramework的MVC:
上面简单的介绍了什么是MVC,让有的同事进一步的了解一下。
QFramework 基于 MVC 的开发模式
所以我们先从最熟知的 MVC 架构开始着手 QFramework 的学习。
实例说明:
有些技术只靠文字不能形象的进行表达和说明,那么我们就通过一些简单的功能来反应技术的点有什么的不同之处
首先我们再unity中搭建一个简单的计数器功能,通过加减来控制技术器的数值变化:
然后我们用平时我们最常用的方法实现它
using UnityEngine;
using UnityEngine.UI;
// Controller
public class CounterAppController : MonoBehaviour
{
// View:在 QFramework 的 MVC 定义里就是提供关键组件的引用
private Button mBtnAdd;
private Button mBtnSub;
private Text mCountText;
// Model:非常简单,只有一个成员变量,但是在这里它其实并不算是一个 Model,他只是要在
// View 中显示的一个数据而已
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导入工程之后,我们需要对代码进行修改:
using UnityEngine;
using UnityEngine.UI;
// 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 只是其功能的一小部分。
这里要注意一点,Model 的引入是为了解决数据共享的问题,而不是说单只是为了让数据和表现分离,这一点是非常重要的一点。数据共享分两种:空间上的共享和时间上的共享。空间的共享很简单,就是多个点的代码需要访问 Model 里的数据。时间上的共享就是存储功能,将上一次关闭 App 之前的数据存储到一个文件里,这次打开时获得上次关闭 App 之前的数据。虽然我们上手了 MVC,但是这样的 MVC 还有很多问题,我们下一篇继续解决。