1.什么是MVC

MVC分别代表Model – View – Controller
Model – 模型层,也就是说,他只负责数据
View – 视图层,也就是说,他只负责更新UI
Controller – 控制层,他只负责控制,并关联Model和View
这样说大家可能看不懂,看一下这个图会更清晰一点

View 和Model基本不会直接交流,而是通过Controller进行交流

2. 准备实现的功能

在本文中以这样一个例子去讲解MVC

首先,我们搭建这样一个画面
在Canvas下创建两个Text,一个Button

创建后并调整的画面是这样的

点击按钮,Ex会减少100,生命值加100

3.设计Model层

首先是Model,最为重要的模型层,我们把上面的功能抽象成模型,只负责数据的迭代
1.HP
2.EX
3.用来升级的方法
无非就是这三个要素,首先看我的设计,在代码里会有详细的注释

//这个单参数委托,用来传递View的更新UI方法,等下就懂了哦public delegate void BroadcastAction (PlayerModel model);public class PlayerModel//这个也不使用Unity的API,不继承Mono{//生命和经验两个变量private int hp = 100;private int ex = 10000;//用属性限制修改,我们不希望模型层之外的任何地方修改变量,修改只在模型层内进行public int HP {get { return hp; }}public int Ex { get { return ex; } }//这样就可以升级了,扣100经验,增加100生命public void AddLev(){hp+=100;ex-=100;//用这个方法通知View层修改数据,这个方法是接下来我们要做的,而不是原来就有的APIBroadcast();}//-------------------------分割线------------------------------------------//通过建立一个注册机制,来通知所有View去更新数据private BroadcastAction actions;//一旦注册也就更新public void Register(BroadcastAction action){actions += action;Broadcast();}//通知View层更新UI,而不是直接去View层改public void Broadcast(){actions" />Invoke(this);}//--------------------------------------分割线----------------------------//使用单例模式,方便外界去获取Model层,同时保证每个Model层唯一,不懂单例可以了解一下private static PlayerModel model;public static PlayerModelInstance{get {//获取时如果是空,则创建一个实例if (model == null) model = Activator.CreateInstance<PlayerModel>();return model; }}}}

嘿哈嘿哈,有没有发现每个Model都有后两部分内容啊,在文章末尾会简化这一过程
.

4.搭建PlayerView

在View层里,我们只负责更新UI

using UnityEngine.UI;public class PlayerView : MonoBehaviour //需要更新UI,继承Mono{//先public两个文本框,在Unity内可以通过拖拽去绑定UIpublic Text txt1,txt2;//我们只希望这里更新UI,但是我们要获取Model层的数据,也只有那里有数据//所以我们把Moddel作为参数传入,但传入这个参数不能是View层去做,而是Controller去传入,View层只被动接受//也就是说,一旦Model有变化,就通知Controller去调用View层方法去更新UIpublic void UpdateView(PlayerModel model){//更新两个文本框的内容txt1.text = "HP:"+model.HP.ToString();txt2.text = "Ex:"+model.Ex.ToString();}}

View层就完成了,细心的小伙伴发没发现每个View都会用UpdateView这个方法呢
.

5. 搭建Controller

接下来就是关联Model和View

这Controller这一层,只负责玩家的控制MV的绑定

using UnityEngine.UI;public class PlayerController : Controller{//绑定Viewpublic View m_View;//绑定Buttonpublic Button btn;private void Start(){//绑定MVC的过程,我们只需要把View的更新方法绑到Model的通知列表里PlayerModel.Instance.Register(m_View.UpdateView);//如果点击按钮执行升级,为按钮添加点击事件btn.onClick.AddListener(PlayerModel.Instance.AddLev);}}

此时我们只要为这些变量添加绑定就可以了

有没有眼前一亮的感觉,无论计算方法怎么变,我们改的都仅仅是Model层的数据
而不关心UI的更新,或者玩家的控制
同理,我们处理UI的时候也仅仅关心UI的更新,而不考虑计算方法
实现了M – V – C 的分层,但是我们发现其中MVC都有一定的重复和规范,接下来我们着重去实现这些规范

规范的实现

1. View基类

不难发现,想要更新UI就必须继承Mono,然后想要能被Model通知更新,就需要这个共性的方法,我们只需要继承这个方法,实现这个方法,View层就成了

using UnityEngine;public abstract class View:MonoBehaviour{public abstract void UpdateView(Model model);}

2. Controller基类

using UnityEngine;public abstract class Controller:MonoBehaviour{//这个方法我们不需要用户自己去实现,每次都一样,提供就行了,继承本类调用一次protected void Bind(View view,Model model){model.Register(view.UpdateView);}}

3.Model基类

public delegate void BroadcastAction (Model model);public abstract class Model{//这是注册部分private BroadcastAction actions;public void Register(BroadcastAction action){actions += action;Broadcast();}public void Broadcast(){actions" />Invoke(this);}}//多继承差不多约等于类的合并,分开是因为可以加上泛型T,直接通过类名去调单例,同时保留基类Model的兼容性public abstract class Model<T>:Model{//这是单例部分private static T model;public static TInstance{get {if (model == null) model = Activator.CreateInstance<T>();return model; }}}

代码简化

1.View层

这里好处不是写的少了,而是约束所有人实现View必须写这个UpdateView方法,不然就报错,如果有人View层更新写了别的方法,会引起混乱,这样有一个统一标准

using UnityEngine.UI;public class PlayerView : View{public Text txt1, txt2;public override void UpdateView(Model model){PlayerModel playerModel = (PlayerModel)model;txt1.text = "HP:"+playerModel.HP.ToString();txt2.text = "Ex:"+playerModel.Money.ToString();}}

2.Model层

可以看到Model层直接少了两大部分,代码量骤减,

public class PlayerModel :Model<PlayerModel>{private int hp = 100;private int ex = 10000;public int HP{get { return hp; }}public int Ex { get { return ex; } }public void AddLev(){hp+=100;ex-=100;//通知View更新UIBroadcast();}}

3.Controller

这里的作用就是一个Bind方法,让代码看起来舒服那么一点点,一点点,作用其实有限
也容易理解一点

using UnityEngine.UI;public class PlayerController : Controller{public View view;public Button btn;private void Start(){Bind(view, PlayerModel.Instance);btn.onClick.AddListener(PlayerModel.Instance.AddLev);}}

结束

到这里,如果你认真看了这些代码,并且会使用Unity,我相信你已经理解了MVC的初级使用
哪怕是在其他语言中,其他引擎或者开发工具里,也都是一样的思路,只不过更加丰满妖娆
而不像本文只有骨架,有三分神似,我们所见只是天边一角
无限的未来等着我们去探索