Intro
QFramework 是一个由凉鞋开发的轻量级的框架,狭义上的 QFramework 是指仓库里的那个 QFramework.cs 文件,提供的是一套数据管理的方式,他由 Architecture, System, Controller, Model 组成,辅以 TypeEventSystem, Command 等消息通知手段,以及可有可无,存在感比较低的 Utility 和 Query。
广义上的 QFramework 是一个包含了 QFramework.cs 以及相关配套插件的一套生态,包括了 UIKit, ResKit, AudioKit, SingletonKit 和 FsmKit 等工具。
QFramework 的架构
QFramework 在使用上的架构,大致分为了四层。分别是表现层,系统层,数据层和工具层。
在这些层级中,表现层(Controller)居于最顶层,可以获取 System 层、Model 层的引用,也可以发送事件和监听 Event。
System 位于表现层和数据层之间,可以获取其他的 System 层、Model 层的引用,也可以发送事件和监听 Event。
Model 几乎位于系统的最底层,他不能去影响系统层和表现层的任何东西,因此它只能发送和监听 Event。
Utility 是系统的最最最底层,只提供一些运行上的工具支撑,除了被其他层调用外,无法对系统做任何的影响。
block-beta
columns 4
Controlle:4
BattleSystem NetworkSystem StoreSystem AchievementSystem
PlayerModel GameModel:2 ConfigModel
ResUtility ParserUtility DeviceUtility SdkUtility
通过阅读源代码,我们可以清晰地画出 QFramework 的类图。
classDiagram
direction TB
class IBelongToArchitecture {
- GetArchitecture()* IArchitecture
}
ICanInit --|> IBelongToArchitecture
class ICanInit {
- Initialized: bool
- Init()* void
- Deinit()* void
}
class ICanRegisterEvent
ICanRegisterEvent --|> IBelongToArchitecture
class ICanGetModel
ICanGetModel --|> IBelongToArchitecture
class ICanGetUtility
ICanGetUtility --|> IBelongToArchitecture
class ICanSetArchitecture
ICanSetArchitecture --|> IBelongToArchitecture
class ICanSendEvent
ICanSendEvent --|> IBelongToArchitecture
class ICanSendQuery
ICanSendQuery --|> IBelongToArchitecture
class ICanSendCommand
ICanSendCommand --|> IBelongToArchitecture
class ICanRegisterEvent
ICanRegisterEvent --|> IBelongToArchitecture
class ICanGetModel
ICanGetModel --|> IBelongToArchitecture
class ICanGetUtility
ICanGetUtility --|> IBelongToArchitecture
class ICanSetArchitecture
ICanSetArchitecture --|> IBelongToArchitecture
class ICanSendEvent
ICanSendEvent --|> IBelongToArchitecture
class ICanSendQuery
ICanSendQuery --|> IBelongToArchitecture
class ICanSendCommand
ICanSendCommand --|> IBelongToArchitecture
class IModel
IModel --|> ICanSetArchitecture
IModel --|> ICanSendEvent
IModel --|> ICanInit
IModel --|> IBelongToArchitecture
class ICanGetSystem
ICanGetSystem --|> IBelongToArchitecture
class ISystem
ISystem --|> ICanSetArchitecture
ISystem --|> ICanGetModel
ISystem --|> ICanGetUtility
ISystem --|> ICanRegisterEvent
ISystem --|> ICanSendEvent
ISystem --|> ICanGetSystem
ISystem --|> ICanInit
ISystem --|> IBelongToArchitecture
class IController
IController --|> IBelongToArchitecture
IController --|> ICanSendCommand
IController --|> ICanGetSystem
IController --|> ICanGetModel
IController --|> ICanRegisterEvent
IController --|> ICanSendQuery
IController --|> ICanGetUtility
class AbstractSystem {
- mArchitecture: IArchitecture
- GetArchitecture()* IArchitecture
- SetArchitecture(architecture: IArchitecture)
+ Initialized: bool
- Init()
- DeInit()
}
AbstractSystem --|> ISystem
class AbstractModel {
- mArchitecture: IArchitecture
- GetArchitecture()
- SetArchitecture(architecture: IArchitecture)
+ Initialized: bool
- Init()
- DeInit()
}
AbstractModel --|> IModel
通过抽象出各种行为的接口(如 ICanSendEvent, ICaGetModel, ICanGetSystem 等),QFramework 实现了各个层次的对象的行为控制。
并且我们可以清晰地看到,所有的层级控制都需要继承 IBelongToArchitecture 接口,这也是 QFramework 能够返回 System 层和 Model 层对象引用的核心。
根据QFramework的教程,继承了 IBelongToArchitecture 接口的对象需要返回一个IArchitecture 接口,通常来说我们将调用某个继承了Architecture
而这个接口将在 Architecture
说的简单一些,Architecture
以下是 IController 对象初始化整个 QFramework 架构的例子。
graph TD
IController对象被实例化 -->
IController中调用了QFramework相关的方法 -->
相关方法调用IController的GetArchitecture方法获取相关Architecture的引用 -->
Architecture调用MakeSureArchitecture方法创建引用并返回IArchitecture接口 -->
相关方法通过IArchitecture接口获取Architecture所有注册的对象 -->
获取到资源的相关方法开始运行
TypeEventSystem
TypeEventSystem 是一个基于类型系统实现的一个事件收发器。核心的事件注册与触发依赖于 EasyEvents 类的 mGlobalEvents 字典。
classDiagram
direction TD
class IUnRegister
class IEasyEvent {
+ Register(Action onEvent) IUnRegister
}
IEasyEvent -- IUnRegister
class EasyEvent {
- mOnEvent: Action
+ Register(Action onEvent) IUnRegister
+ RegisterWithACall(Action onEvent) IUnRegister
+ UnRegister(Action onEvent) void
+ Trigger() void
}
EasyEvent --|> IEasyEvent
class EasyEvents {
- s_mGlobalEvents: EasyEvents
+ s_Get~T~() T
+ s_Register~T~()
- mTypeEvents: Dictionary~Type, IEasyEvent~
+ AddEvent~T~() void
+ GetEvent~T~() T
+ GetOrAddEvent~T~() T
}
EasyEvents -- IEasyEvent
class TypeEventSystem {
- mEvents: EasyEvents
+ s_Global: TypeEventSystem
+ Send~T~()
+ Register~T~(Action onEvent) IUnRegister
+ UnRegister~T~(Action onEvent) void
}
TypeEventSystem -- EasyEvent
TypeEventSystem -- EasyEvents
QFramework 使用 TypeEventSystem 有两种方法,一种是继承了 QFramework 的接口后调用事件的发送与监听(即 this.SendEvent 调用),一种是直接使用 TypeEventSystem 的静态方法调用事件的发送与监听(即TypeEventSystem.Global.SendEvent )。
Architecture 中的事件调用使用的是在 Architecture 中实例化的 TypeEventSystem。
// Architecture
private TypeEventSystem mTypeEventSystem = new TypeEventSystem();
public void SendEvent
public void SendEvent
public IUnRegister RegisterEvent
public void UnRegisterEvent
TypeEventSystem 中的事件调用使用的是 TypeEventSystem 自己的单例。
public class TypeEventSystem
{
private readonly EasyEvents mEvents = new EasyEvents();
public static readonly TypeEventSystem Global = new TypeEventSystem();
public void Send
public void Send
public IUnRegister Register
public void UnRegister
{
var e = mEvents.GetEvent
e?.UnRegister(onEvent);
}
}
AbstractCommand
QFramework 在执行命令时,首先为 Command 设置 Architecture,然后调用 ICommand 的 Execute 方法。
// Architecture 执行 Command
public TResult SendCommand
public void SendCommand
protected virtual TResult ExecuteCommand
{
command.SetArchitecture(this);
return command.Execute();
}
protected virtual void ExecuteCommand(ICommand command)
{
command.SetArchitecture(this);
command.Execute();
}
BindableProperty
BP 的实现相当简单,只要 Value 被重新赋值了,就会触发 mOnValueChanged。
但局限性也很明显,那就是只能处理值类型的数据,引用类型的数据(比如 Dictionary)一般不会被重新赋值,外界使用的时候也只是修改引用类型数据的内部数据。
public class BindableProperty
{
public BindableProperty(T defaultValue = default) => mValue = defaultValue;
protected T mValue;
public static Func
public BindableProperty
{
Comparer = comparer;
return this;
}
public T Value
{
get => GetValue();
set
{
if (value == null && mValue == null) return;
if (value != null && Comparer(value, mValue)) return;
SetValue(value);
mOnValueChanged.Trigger(value);
}
}
protected virtual void SetValue(T newValue) => mValue = newValue;
protected virtual T GetValue() => mValue;
public void SetValueWithoutEvent(T newValue) => mValue = newValue;
private EasyEvent
public IUnRegister Register(Action
{
return mOnValueChanged.Register(onValueChanged);
}
public IUnRegister RegisterWithInitValue(Action
{
onValueChanged(mValue);
return Register(onValueChanged);
}
public void UnRegister(Action
IUnRegister IEasyEvent.Register(Action onEvent)
{
return Register(Action);
void Action(T _) => onEvent();
}
public override string ToString() => Value.ToString();
}
总结
如果需要用非常非常简洁的话来描述 QFramework,它是一个有着良好权限控制的 IOC 容器。
Reference
GitHub: QFramework
QFramework Wiki