Unity MVC框架

一、介绍MVC

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。

Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
  通常模型对象负责在数据库中存取数据。

View(视图)是应用程序中处理数据显示的部分。
  通常视图是依据模型数据创建的。

Controller(控制器)是应用程序中处理用户交互的部分。
  通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

二、代码实现(基于Unity)

有事件管理中心(class MVC)的MVC模式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public abstract class Model
{
//名字标识
public abstract string Name { get; }

//发送事件
protected void SendEvent(string eventName,object data=null)
{
MVC.SendEvent(eventName, data);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class View : MonoBehaviour {

//名字标识
public abstract string Name { get; }

//事件关心列表
[HideInInspector]
public List<string> AttentionList = new List<string>();

//初始化事件关心列表,在注册视图的时候被调用
public virtual void RegisterAttentionEvent() { }

//处理事件
public abstract void HandleEvent(string name, object data);

//发送事件
protected void SendEvent(string eventName, object data = null)
{
MVC.SendEvent(eventName, data);
}

//获取模型
protected T GetModel<T>()
where T:Model
{
return MVC.GetModel<T>() as T;
}


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public abstract class Controller
{
//执行事件
public abstract void Execute(object data);

//获取模型
protected T GetModel<T>()
where T : Model
{
return MVC.GetModel<T>() as T;
}

//获取视图
protected T GetView<T>()
where T : View
{
return MVC.GetView<T>() as T;
}
//注册模型
protected void RegisterModel(Model model)
{
MVC.RegisterModel(model);
}
//注册视图
protected void RegisterView(View view)
{
MVC.RegisterView(view);
}
//注册控制器
protected void RegisterController(string eventName,Type controllerType)
{
MVC.RegisterController(eventName, controllerType);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public static class MVC
{
//资源
//名字 -- model(保存的是实例对象)
public static Dictionary<string, Model> Models = new Dictionary<string, Model>();
//名字 -- view(保存的是实例对象)
public static Dictionary<string, View> Views = new Dictionary<string, View>();
//事件名字 -- 类型 (保存的是类)
public static Dictionary<string, Type> ComandMap = new Dictionary<string, Type>();

//注册view,注意这里的view其实是由 继承于View的子类上溯而来(下同)
public static void RegisterView(View view)
{
//防止view的重复注册
if(Views.ContainsKey(view.Name))
{
Views.Remove(view.Name);
}
view.RegisterAttentionEvent();//调用视图方法,注册视图关心事件,存放在关心事件列表中
Views[view.Name] = view;
}

//注册model
public static void RegisterModel(Model model)
{
Models[model.Name] = model;
}

//注册controller 将一个事件执行器放入字典,以eventName为键,Type类型是类,就是放入一个需要被实例化的类,使用的时候必须要实例化再使用
public static void RegisterController(string eventName,Type controllerType)
{
ComandMap[eventName] = controllerType;
}

//获取model,T是外部传进来的模型脚本,该脚本必须继承自Model
public static T GetModel<T>()
where T:Model
{
foreach(var m in Models.Values)
{
//m肯定是Model类型,但是这个m 是由 继承于Model的脚本上溯而来的,这里会进行下溯 看看m是否等于T
if (m is T)
{
//若等于,则先强转为T脚本 再返回.
return (T)m;
}
}
return null;
}

//获取view
public static T GetView<T>()
where T : View
{
foreach (var v in Views.Values)
{
if (v is T)
{
return (T)v;
}
}
return null;
}

//发送事件(对于外部调用者来说该方法是发送事件,对于内部方法来说是不同的控制器和视图处理事件),命名上不要求和我一致,只要见名知意即可.
public static void SendEvent(string eventName,object data=null)
{
//在这里可发现一个事件对应一个Controller处理,具体事件继承于抽象事件,一个具体事件的诞生首先要进行继承于Controller 重写Execute 注册入CommandMap字典三步骤
//controller 执行,eventName是事件名称,若在控制器字典内存在该事件名称,则肯定会有一个控制器去处理该事件
if(ComandMap.ContainsKey(eventName))
{
//t脚本类是继承于Controller类的,不然下面无法转换为Controller
Type t = ComandMap[eventName];
//根据字典取出来的t,去实例化一个对象,并且object转化为Controller类型,因为t对象继承于Controller所以可以转化
Controller c = Activator.CreateInstance(t) as Controller;
//执行被t所重写的Execute方法,data是传入的数据(object类型)
c.Execute(data);
}
//view处理
//遍历所有视图,注意:一个视图允许有多个事件,而且一个事件可能会在不同的视图触发,而事件的内容不确定(事件可理解为触发消息)
foreach(var v in Views.Values)
{
//视图v的关心事件列表中存在该事件
if(v.AttentionList.Contains(eventName))
{
//让视图v执行该事件eventName,附带参数data
//HandleEvent方法是通过switch case的形式处理不同的事件
v.HandleEvent(eventName, data);
}
}
}
}

Unity MVC框架
https://newztx.github.io/2024/07/24/Unity MVC框架/
作者
Cranky Dove
发布于
2024年7月24日
许可协议