最近在做一些简单的小型项目,学习了MVC框架:https://blog.csdn.net/ff_0528/article/details/82699360
但是实际使用时发现并不是特别顺手,因为实际项目与数据层几乎没有交互,M和C基本沦为摆饰,虽然能实现解耦但是增加了开发时间成本,实际的维护成本也没有降低,就将上述MVC框架精简了一下,删掉了M和C优化了一些细节,生成了ViewSingleton精简框架。
该框架实现了基于事件触发的系统,但是不完全解耦,项目小的时候通过单例进行适当的耦合度方便快速开发,然后将程序主流程进行事件分配,可维护性高。尤其是针对那种流程性的小项目,比如第一步要做xxx,第二步做xxx,通过事件控制每一步,然后有跨脚本调用需求的,直接单例过去就完事了~
首先编写一个View,继承mono,实现基础的注册单例、注册关心事件、发送消息、接收消息处理:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class View : MonoBehaviour
{
//注册本身
public void RegisterSelf()
{
EventController.RegisterView(this);
}
// 视图层关心的事件列表
[HideInInspector]
public List<Consts> attentionEvents = new List<Consts>();
// 注册视图关心的事件
public virtual void RegisterViewEvents()
{
}
//发送消息
protected void SendEvent(Consts eventName, object data = null)
{
EventController.SendEvent(eventName, data);
}
// 视图层事件处理
public abstract void HandleEvent(Consts eventName, object data);
}
然后实现一个基于View的单例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class ViewSingleton<T> : View where T : View
{
private static T instance = null;
public static T Instance
{
get
{
if (null == instance)
{
instance = FindObjectOfType(typeof(T)) as T;
if (instance == null) instance = new GameObject("Single of " + typeof(T).ToString(), typeof(T)).GetComponent<T>();
}
return instance;
}
}
protected virtual void Awake()
{
if (instance == null) instance = this as T;
}
}
再编写事件控制系统EventController,用于注册View和发送事件:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class EventController
{
private static Dictionary<string, View> views = new Dictionary<string, View>(); //名字---视图
//注册视图
public static void RegisterView(View view)
{
string name = view.GetType().ToString();
if (views.ContainsKey(name)) return;
views[name] = view;
view.RegisterViewEvents(); //注册关心的事件
}
//发送事件
public static void SendEvent(Consts eventName, object data = null)
{
//视图层
foreach (View v in views.Values)
{
if (v.attentionEvents.Contains(eventName))
v.HandleEvent(eventName, data);
}
}
}
最终使用的时候就很简单了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UITest : ViewSingleton<UITest>
{
new void Awake()
{
//在每个物体Awake的时候自己注册,也可以用FindObjectOfType在其他脚本搜到后注册
RegisterSelf();
}
private void Start()
{
//发送事件
SendEvent(Consts.E_StartUp);
}
public void Test()
{
Debug.Log("test");
}
public override void RegisterViewEvents()
{
//添加关心的事件
attentionEvents.Add(Consts.E_StartUp);
}
public override void HandleEvent(Consts eventName, object data)
{
switch (eventName)
{
case Consts.E_StartUp:
{
//若事件触发,调用相关函数
Debug.Log("E_StartUp");
Test();
}
break;
}
}
}
还需要一个小小的枚举来记录事件:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Consts
{
//用枚举记录所有事件
E_StartUp,
E_OpenUI
}
如果不想要单例也很简单,直接继承View即可,如果不想要继承View的单例,就重写一个单例即可,附赠单例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance = null;
public static T Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType(typeof(T)) as T;
if (instance == null) instance = new GameObject("Chinar Single of " + typeof(T).ToString(), typeof(T)).GetComponent<T>();
}
return instance;
}
}
private void Awake()
{
if (instance == null) instance = this as T;
}
}