大家好,欢迎来到IT知识分享网。
一、介绍MVC
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
通常模型对象负责在数据库中存取数据。
通常视图是依据模型数据创建的。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
二、MVC框架(偏向游戏编程)
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);
}
}
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;
}
}
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);
}
}
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);
}
}
}
}
思考:为什么Controller类的注册方法与View和Model有所不同?
其实,这种注册方法只是图方便,因为如果传递的是一个对象进来,需要new XxxController(),而Controller直接传递一个Type就无须new,直接用typeof(XxxxController)转化为Type,而注册的时候肯定是知道这个Controller处理什么事件的.
这里有个内在关系,即Controller只处理Controller名字的事件,这个要用一个静态类来保存这些Controller的名字,我们是通过这些名字来注册和发送事件的,这些名字也是View视图关心事件的名字。
假设:我新建了一个控制器StartGameController,它的名字叫E_StartGame ,E代表的是事件Event的意思
而且 我新建了一个视图MainView,它的名字叫V_Main,V代表的是视图View的意思,该视图的关心事件注册了E_StartGame
当我们调用MVC.SendEvent(“E_StartGame”)时,就会触发控制器StartGameController的Execute方法(一对一处理),以及视图MainView的HandleEvent方法(一对多处理),HandleEvent方法通过Switch(eventName) case “E_StartGame”: … break; 这样来处理E_StartGame事件.
上面的”E_StartGame”很容易写错,所以用一个静态类来保存,防止出错。
注册视图和注册模型的名字,同样也可以分别用两个静态类来保存。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/10821.html