简单介绍 QFramework

36578130 2025-10-12 10:34:29 作者: admin 阅读: 2744
简单介绍 QFramework

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的类,并返回它的Interface 属性。

而这个接口将在 Architecture 未初始化时自动调用 Architecture 抽象类的 MakeSureArchitecture() 方法,该方法将为 Architecture 创建一个 mArchitecture 实例,并调用 Init 方法进行框架初始化。

说的简单一些,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() where TEvent : new() => mTypeEventSystem.Send();

public void SendEvent(TEvent e) => mTypeEventSystem.Send(e);

public IUnRegister RegisterEvent(Action onEvent) => mTypeEventSystem.Register(onEvent);

public void UnRegisterEvent(Action onEvent) => mTypeEventSystem.UnRegister(onEvent);

TypeEventSystem 中的事件调用使用的是 TypeEventSystem 自己的单例。

public class TypeEventSystem

{

private readonly EasyEvents mEvents = new EasyEvents();

public static readonly TypeEventSystem Global = new TypeEventSystem();

public void Send() where T : new() => mEvents.GetEvent>()?.Trigger(new T());

public void Send(T e) => mEvents.GetEvent>()?.Trigger(e);

public IUnRegister Register(Action onEvent) => mEvents.GetOrAddEvent>().Register(onEvent);

public void UnRegister(Action onEvent)

{

var e = mEvents.GetEvent>();

e?.UnRegister(onEvent);

}

}

AbstractCommand

QFramework 在执行命令时,首先为 Command 设置 Architecture,然后调用 ICommand 的 Execute 方法。

// Architecture 执行 Command

public TResult SendCommand(ICommand command) => ExecuteCommand(command);

public void SendCommand(TCommand command) where TCommand : ICommand => ExecuteCommand(command);

protected virtual TResult ExecuteCommand(ICommand command)

{

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 : IBindableProperty

{

public BindableProperty(T defaultValue = default) => mValue = defaultValue;

protected T mValue;

public static Func Comparer { get; set; } = (a, b) => a.Equals(b);

public BindableProperty WithComparer(Func comparer)

{

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 mOnValueChanged = new EasyEvent();

public IUnRegister Register(Action onValueChanged)

{

return mOnValueChanged.Register(onValueChanged);

}

public IUnRegister RegisterWithInitValue(Action onValueChanged)

{

onValueChanged(mValue);

return Register(onValueChanged);

}

public void UnRegister(Action onValueChanged) => mOnValueChanged.UnRegister(onValueChanged);

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

相关推荐