MVC设计模式

在当今的软件开发领域,MVC(Model-View-Controller)设计模式已经成为了一种广泛使用的架构模式。它为应用程序提供了一种结构化的方法,将数据、用户界面和业务逻辑分开,从而使得应用程序更易于维护、扩展和重用。

一、MVC的概述
MVC是一种分层的设计,主要用于解决UI交互方面的经验体系。它包括Model、View和Controller三部分,分别负责数据的存储、视图界面的显示和业务逻辑的处理。MVC模式有助于降低代码的耦合度,实现界面、数据和逻辑的分离,从而易于代码的维护和拓展。

二、MVC的组成部分
模型(Model):模型是应用程序的数据和业务逻辑的核心。它负责处理与数据相关的所有操作,例如数据的增删改查、验证和持久化等。模型是与数据源直接交互的部分,不涉及用户界面或用户输入的处理。
视图(View):视图是应用程序的用户界面。它负责显示数据给用户,并接收用户的输入。视图只关注如何展示数据,而不关心数据从哪里来或应该如何处理。
控制器(Controller):控制器是模型和视图之间的中介。它负责接收用户的输入,处理这些输入,并更新模型和视图。控制器的主要任务是处理用户交互,并根据用户的操作更新数据和界面。控制器不包含任何与数据或用户界面相关的代码,而是专注于处理用户交互和协调模型和视图之间的通信。

三、MVC的优势
MVC模式的优点主要表现在以下几个方面:

解耦:MVC模式将应用程序的不同部分(数据、用户界面和业务逻辑)分离,降低了它们之间的耦合度。这使得开发人员可以独立地专注于各自的部分,提高了开发效率和代码的可维护性。
代码组织:MVC模式为应用程序提供了一种清晰的代码组织结构,使得代码更加模块化和易于管理。这种结构也有助于团队之间的协作,使得不同的开发人员可以专注于不同的部分。
可扩展性:由于MVC模式将应用程序的不同部分分离,因此当应用程序需要扩展时,可以更容易地添加新的功能或模块,而不会对现有的代码造成太大的影响。
可重用性:MVC模式使得模型、视图和控制器的分离,这使得它们可以独立地重用。例如,同一个模型可以与不同的视图或控制器一起使用,或者同一个视图可以用在不同的应用程序中。
易于测试和维护:由于MVC模式将应用程序的不同部分分离,因此可以更容易地对每个部分进行单元测试和集成测试。此外,由于代码的模块化结构,使得代码更易于维护和修改。

四、Unity游戏开发中的MVC
这里提供一个MVC模式的基本功能框架。

Model

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//Model基类
public class BaseModel
{
    public BaseController controller;

	//有参构造
    public BaseModel(BaseController control)
    {
        this.controller = control;
    }
	//无参构造
    public BaseModel()
    {
        
    }
	//初始化
    public virtual void Init()
    {
        
    }
}

View

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

//面板基类,因为需要挂载到场景对象上需要继承MonoBehaviour
public class BaseView : MonoBehaviour
{
	//面板ID属性
    public int ViewId { get; set; }
    //面板控制器
    public BaseController Controller { get; set; }
	//面板cavans
    protected Canvas _canvas;

    protected Dictionary<string,GameObject> _ObjCache = new Dictionary<string, GameObject>();//面板中对象缓存

    private bool _isInit = false; //是否初始化

    void Awake()
    {
        _canvas = gameObject.GetComponent<Canvas>();
        OnAwake();
    }

    void Start()
    {
        OnStart();
    }

    protected virtual void OnAwake()
    {

    }

    protected virtual void OnStart()
    {

    }
	
	//调用指定控制器的注册方法
    public void ApplyControllerFunc(int controllerKey, string eventName, params object[] args)
    {
        this.Controller.ApplyControllerFunc(controllerKey,eventName,args);
    }

	//调用自己控制器的注册方法
    public void ApplyFunc(string eventName, params object[] args)
    {
        this.Controller.ApplyFunc(eventName,args);
    }

	//关闭界面
    public virtual void Close(params object[] args)
    {
        SetVisible(false);
    }

	//销毁界面
    public void DestroyView()
    {
        Controller = null;
        Destroy(gameObject);
    }

	//初始化数据
    public virtual void InitData()
    {
        _isInit = true;
    }
	
	//初始化UI
    public virtual void InitUI()
    {
        
    }

    public bool IsInit()
    {
        return _isInit;
    }

    public bool IsShow()
    {
        return _canvas.enabled == true;
    }

    public virtual void Open(params object[] args)
    {
        
    }

    public void SetVisible(bool value)
    {
        this._canvas.enabled = value;
    }

	//查找面板中的对象
    public GameObject Find(string name)
    {
        if(_ObjCache.ContainsKey(name))
        {
            return _ObjCache[name];
        }
        _ObjCache.Add(name,transform.Find(name).gameObject);
        return _ObjCache[name];
    }

    public T Find<T>(string name) where T:Component
    {
        GameObject obj = Find(name);
        return obj.GetComponent<T>();
    }
}

Controller

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//控制器基类
public class BaseController
{
    private Dictionary<string,Action<object[]>> message;//事件列表

    protected BaseModel model;//模版数据

    public BaseController()
    {
        message = new Dictionary<string, Action<object[]>>();
    }

    //注册后,调用的初始化函数(要求所有控制器初始化后执行)
    public virtual void Init()
    {

    }

    public virtual void OnLoadView(IBaseView view){}//加载视图

    //打开视图
    public virtual void OpenView(IBaseView view)
    {

    }

    //关闭视图
    public virtual void CloseView(IBaseView view)
    {

    }

    //注册模版事件
    public void RegisterFunc(string eventName,Action<object[]> callback)
    {
        if(message.ContainsKey(eventName))
        {
            message[eventName]+=callback;
        }
        else
        {
            message.Add(eventName,callback);
        }
    }

    //移除模版事件
    public void UnRegisterFunc(string eventName)
    {
        if(message.ContainsKey(eventName))
        {
           message.Remove(eventName);
        }
    }

    //触发本模块事件
    public void ApplyFunc(string eventName, params object[] args)
    {
        if(message.ContainsKey(eventName))
        {
            message[eventName].Invoke(args);
        }
        else
        {
            Debug.Log("error:"+eventName);
        }
    }

    //触发其他模板的事件
    public void ApplyControllerFunc(int controllerKey,string eventName, params object[] args)
    {
        GameApp.ControllerManager.ApplyFunc(controllerKey,eventName,args);
    }

    //
    public void ApplyControllerFunc(ControllerType controllerType,string eventName,params object[] args)
    {
        ApplyControllerFunc((int)controllerType,eventName,args);
    }

    //设置模型数据
    public void SetModel(BaseModel model)
    {
        this.model = model;
        this.model.controller = this;
    }

    //得到模型数据
    public BaseModel GetModel()
    {
        return model;
    }

    //得到模型数据泛型
    public T GetModel<T>() where T:BaseModel
    {
        return model as T;
    }

    //得到指定控制器控制的模型
    public BaseModel GetControllerMode(int controllerKey)
    {
        return GameApp.ControllerManager.GetControllerModel(controllerKey);
    }

    //删除控制器
    public virtual void Destroy()
    {
        RemoveModuleEvent();
        RemoveGlobalEvent();
    }

    //初始化模板事件
    public virtual void InitModuleEvent()
    {

    }

    //移除模板事件
    public virtual void RemoveModuleEvent()
    {

    }

    //初始化全局事件
    public virtual void InitGlobalEvent()
    {

    }

    //移除全局事件
    public virtual void RemoveGlobalEvent()
    {

    }

}

ViewManager

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

//视图信息类
public class ViewInfo
{
    public string PrefabName;//视图预制体
    public Transform parentTf;//父节点
    public BaseController controller;//视图所属控制器
    public int sorting_order;//显示层级顺序
}

//视图管理器
public class ViewManager 
{
    public Transform canvasTf;//画布组件
    public Transform worldCanvasTf;//世界画布组件
    Dictionary<int,IBaseView> _opens;//开启的视图列表
    Dictionary<int,IBaseView> _viewCache;//视图缓存
    Dictionary<int,ViewInfo> _views;//注册的视图信息列表

    public ViewManager()
    {
        canvasTf = GameObject.Find("Canvas").transform;
        worldCanvasTf = GameObject.Find("WorldCanvas").transform;
        _opens = new Dictionary<int, IBaseView>();
        _views = new Dictionary<int, ViewInfo>();
        _viewCache = new Dictionary<int, IBaseView>();
    }

    //注册视图信息
    public void Register(int key,ViewInfo viewInfo)
    {
        if(_views.ContainsKey(key)==false)
        {
            //Debug.Log(viewInfo.PrefabName);
            _views.Add(key,viewInfo);
        }
    }

    //注册视图信息
    public void Register(ViewType viewType,ViewInfo viewInfo)
    {
        Register((int)viewType,viewInfo);
    }

    //移除视图信息
    public void UnRegister(int key)
    {
        if(_views.ContainsKey(key))
        {
            _views.Remove(key);
        }
    }

    //移除面板
    public void RemoveView(int key)
    {
        _views.Remove(key);
        _viewCache.Remove(key);
        _opens.Remove(key);
    }

    //移除控制器中的面板视图
    public void RemoveViewByController(BaseController controller)
    {
        foreach(var item in _views)
        {
            if(item.Value.controller == controller)
            {
                RemoveView(item.Key);
            }
        }
    }

    //指定视图是否打开
    public bool IsOpen(int key)
    {
        return _opens.ContainsKey(key);
    }

    //获得指定视图
    public IBaseView GetView(int key)
    {
        if(_opens.ContainsKey(key))
        {
            return _opens[key];
        }
        if(_viewCache.ContainsKey(key))
        {
            return _viewCache[key];
        }
        return null;
    }

    //获得指定视图,泛型
    public T GetView<T>(int key) where T:class,IBaseView
    {
        IBaseView view = GetView(key);
       if(view!=null)
       {
        return view as T;
       }
        return null;
    }

    //销毁指定视图
    public void Destroy(int key)
    {
        IBaseView oldView = GetView(key);
       if(oldView!=null)
       {
            UnRegister(key);
            oldView.DestroyView();
            _viewCache.Remove(key);
       }
    }

    //关闭面板视图
    public void Close(int key,params object[] args)
    {
        Debug.Log(key);
        if(IsOpen(key)==false)
        {
            Debug.Log("界面不存在");
            return;
        }
        IBaseView view = GetView(key);
        if(view!=null)
        {
            _opens.Remove(key);
            view.Close(args);
            _viewCache[key].Controller.CloseView(view);
        }
    }

    //打开指定视图面板
    public void Open(ViewType type,params object[] args)
    {
        Open((int)type,args);
    }

    //打开指定视图面板
    public void Open(int key,params object[] args)
    {
        IBaseView view = GetView(key);
        ViewInfo viewInfo = _views[key];
        if(view ==null)
        {
            string type = ((ViewType)key).ToString();
            GameObject uiObj = GameObject.Instantiate(Resources.Load($"View/{viewInfo.PrefabName}"),viewInfo.parentTf) as GameObject;
            Canvas canvas = uiObj.GetComponent<Canvas>();
            if(canvas==null)
            {
                canvas = uiObj.AddComponent<Canvas>();
            }
            if(uiObj.GetComponent<GraphicRaycaster>()==null)
            {
                uiObj.AddComponent<GraphicRaycaster>();
            }
            //可以设置层级
            canvas.overrideSorting = true;
            //设置层级
            canvas.sortingOrder = viewInfo.sorting_order;
            //为视图添加对应脚本
            view = uiObj.AddComponent(Type.GetType(type)) as IBaseView;
            //设置视图ID;
            view.ViewId = key;
            //设置控制器
            view.Controller = viewInfo.controller;
            //添加到视图缓存
            _viewCache.Add(key,view);
            viewInfo.controller.OnLoadView(view);
        }

        if(this._opens.ContainsKey(key)==true)
        {
            return;
        }
        this._opens.Add(key,view);

        //已经初始化过
        if(view.IsInit())
        {
            view.SetVisible(true);
            view.Open(args);
            viewInfo.controller.OpenView(view);
        }
        else
        {
            view.InitUI();
            view.InitData();
            view.Open(args);
            viewInfo.controller.OpenView(view);
        }
    }
}

这个框架中,Model和View没有直接联系,而是通过Controller来控制Model与View之间的信息通信。BaseController中SetModel让Controller和Model关联,面板在ViewManager注册,而在Register方法中让Controller和View关联。进而让Controller来控制Model与View之间的信息通信。
五、总结
MVC设计模式是一种非常有用的架构模式,它使得应用程序的结构更加清晰和易于维护。通过将数据、用户界面和业务逻辑分离,MVC模式提高了代码的可重用性和可扩展性。但MVC设计模式也有缺陷,由于将逻辑与数据分离,程序员需要了解并设计MVC之间的结构,信息通信方式等等,且这一定程度上让程序更加复杂。

你可能感兴趣的:(Unity,游戏开发,mvc,设计框架)