MVC的理解和实际应用

MVC的理解和实际应用





M=Model
V=View
C=Crontroller

其实百度呀,各种资料呀说一大堆,基本概念是 显示,控制,数据分离。
MFC在我的理解中,目的是更清楚的模块定义,耦合度更低,代码调用的时间轴更清晰,代码的调用关系更清晰。

我自己这几年的工作经验整理一下我对于MVC的理解和使用

Data
Logic
View

Net
Loader
Common

引用关系


Data Logic View 为一个组?一个功能?一个系统,具备这么几个组件。
Net Loader Common 是功能的底层功能。

Data <- Loader
Data <- Common

Logic <-Data
Logic <-Loader
Logic <-Common
Logic <-Net

View <-Logic
View <-Loader
View <-Common
View <-Net

Net <-Common
Loader <- Common

描述:


Data 数据层

数据层 分 静态数据层 网络数据层
1.静态数据 客户端读取配置保存在内存
2.网络数据 由服务器发送给客户端的数据,作为网络数据保存,网络数据是动态数据,是否清空按照功能需求而定
不论是静态数据还是网络数据,都应该是受到保护的Private。外部不应该直接对外保护,也就是外部不能直接对数据进行访问和修改。
静态数据由于是读取的本地配置,本地配置数据是原始数据,可以进行修改,所以一定是只读数据。整个项目内也不可能出现需要对静态数据做修改的操作。

Logic逻辑层

1.网络数据部分

是对服务器返回的网络数据做Set 和 Get的函数,对外开放。
客户端本地操作的Set需要确认操作逻辑的安全性,因为程序本身无法确保数据修改是安全的。
网络层应该无脑的向网络数据存储的数据结构做添加or插入,按照具体功能操作。
Get是对其他Logic和View层暴露 。

2.对网络层的封装

是对网络层 Request和Response方法的封装
因为在这套设计里,Logic逻辑层是一个单例的存在,所以界面操作或者逻辑流程可以直接静态调用对应功能的逻辑层的Request函数,向服务器请求数据。
服务器返回数据后,由网络层抛出到各个功能模块进行处理。
Logic监听Response消息,并且进行处理。 处理 包括保存数据到网络数据的数据结构中,和通知其他功能的逻辑层。

View 视图层

那这个就很易懂了,显示相关的。
界面上的MonoBehaviour相关的扒拉扒拉扒拉一堆。
很多操作其实是放在View层的,所以这么区分逻辑层和视图层,其实很简单,逻辑层主要操作数据,视图层主要操作显示。很多强联网的游戏可能没什么感觉,因为每次操作都和服务器通讯
那么
View点击 -> Logic发送消息 -> server …等待服务器返回 -> Logic保存数据 -> View刷新
所在在这套流程里基本不需要进行区分,各司其事其实很明确。
在短链接的游戏或者通讯频率比较低的?一些项目。比如背包的功能,客户端完全可以一顿操作,调整位置整理呀,之后再发给服务器,那么在我的理解中
View操作缓存数据在View层 -> View刷新 -> Logic发送消息 -> server …等待服务器返回 -> Logic保存数据 -> View检查数据同步 -> View刷新
或者是
View操作 -> View刷新,并且缓存数据在Logic层 -> Logic发送消息 -> server …等待服务器返回 -> Logic保存数据 -> View检查数据同步 -> View刷新
其实流程怎么样是无所谓的,只要合理,就是对的。

Net 网络层
这部分就暂时不说了,其实网络部分的牵涉系统底层。我只了解TCP Socket。UDP什么的,我并不了解。对于TCP相关的,之后有机会再发文章。

Loader 加载器
这部分学问就大了,Unity的内存管理,虽然说不难吧,但是也有很多注意点。这个也是以后再发。

代码:



/// <summary>
/// 一个背包格子的内容;
/// </summary>
public class BagItem
{
	public int m_nID = 0;	// 物品ID
	/*
	 * 其他属性;
	 */
}

/// <summary>
/// 一个道具的内容;
/// </summary>
public class ItemInfo
{
	public string m_strName = "";
	/*
	 * 其他属性;
	 */
}

public class ItemData
{
	private static Dictionary<int, ItemInfo> m_dicBagItems = new Dictionary<int, ItemInfo>();	// 道具ID to 道具信息

	public static ItemInfo GetItem(int nID)
	{
		return null;
	}
}

/// <summary>
/// Logic层
/// </summary>
public class BagLogic
{
	private static Dictionary<int, BagItem> m_dicBagItems = new Dictionary<int, BagItem>();	//格子ID to 格子信息

	public static void Init()
	{
		// 注册网络消息监听一个消息的CallBack:OnMsgCallBack
	}

	public static void Release()
	{
		// 对应Init,移除一个消息的监听;
	}

	public static void OnMsgCallBack(/*(此处应该有消息内容)*/)
	{
		//保存到 m_dicBagItems中
	}

	public static BagItem GetItem()
	{
		return null;
	}
}

/// <summary>
/// View层
/// </summary>
public class UIBag : MonoBehaviour
{
	void Start()
	{
		// 注册网络消息监听一个消息的CallBack:OnMsgCallBack
	}

	void OnDestroy()	// 按照UI管理方法的不同,离开界面是自定义的?还是disable?还是destory?看个人情况
	{
		// 对应Init,移除一个消息的监听;
	}

	public void OnMsgCallBack(/*(此处应该有消息内容)*/)
	{
		BagItem bi = BagLogic.GetItem();    // 通过Logic获取
		ItemInfo getItem = ItemData.GetItem(bi.m_nID);	// 获取静态数据。 静态数据这块 是封装进Logic还是直接调用,其实在我看来没差。还是看具体功能而定。
		//然后把数据刷新到界面上。
	}
}

/// <summary>
/// 游戏的主入口;
/// </summary>
public class GameMain : MonoBehaviour
{
	void Main()
	{
		BagLogic.Init();	// 在游戏开始的时候先注册,那么Logic监听消息的时间一定优先于后打开的界面,因为界面的消息监听是打开后才注册的。网络层向上抛数据一定是有序的。不然这个网络层,可以重写了。
	}
}
    

程序学无止尽。
欢迎大家沟通,有啥不明确的,或者不对的,也可以和我私聊
我的QQ 334524067 神一般的狄狄

猜你喜欢

转载自blog.csdn.net/qq_37776196/article/details/85213007
今日推荐