我正在升级数据与UI轻微结合的设计:
class Object {
UI * ui;
};
class UI {
Object * object;
};
通过UI指针将更新通知推送到ui是相当简单的,但是数据的新要求完全与UI分离,并且对于不同的对象也有多个不同的UI表示,因此单个UI指针不再是它也不允许成为数据层的一部分。
由于物镜数量较多(在数亿的范围内),QObject
比最大值高几倍,因此无法使用类似QObject
和信号的信号。层次结构中的对象。对于UI部分来说,这并不重要,因为一次只能看到一部分对象。
我实现了一个UI注册表,它使用multihash来存储使用Object *
作为键的所有UI,以便能够获取给定对象的UI并发送通知,但是查找并且,由于对象数量较多,UI的注册和注销会产生很大的开销。
所以我想知道是否有一些设计模式可以在分离的层之间以较少的开销发送通知?
澄清:大多数更改都在UI端完成,UI元素保留指向相关对象的指针,因此这不是问题。但是,对UI侧的某些对象进行的某些更改会导致数据层中相关对象中发生的更改,这些更改无法预测,以便请求更新受影响对象的UI。实际上,对一个对象进行的UI上的单个更改可能会导致对其他对象的一系列更改,因此我需要能够通知其最终的UI表示以进行更新以反映这些更改。
答案 0 :(得分:1)
解耦通信的一种通用机制是publish-subscribe pattern。在这种情况下,更新的对象会将通知发布到消息队列,然后消息队列负责通知已注册该队列的UI组件有兴趣接受该特定的通知类。
原则上,这与您已尝试过的UI注册表类似。主要区别在于,要更新的UI组件不仅仅是由引用的Object
标识,而是通过通知类型标识。
这允许在特异性和状态保持之间进行权衡:如果设置模型使得与Object
obj
相关联的每个UI组件都会在obj
的每次更新时得到通知,然后它相当于UI注册表。另一方面,可以安排模型使得每当Object
的某个子类别发布更新时通知某些UI组件,然后每个组件可以检查自己是否需要基于其修改其状态。通知的内容。极端情况下,任何Object
发布的任何消息都可以通知每个UI对象,这相当于全局的“更新-UI-状态”方法。
发布 - 订阅模型既包含这两个极端,也包含介于两者之间的范围,您可以在其中找到合适的折衷方案。
答案 1 :(得分:0)
我设法提出了一个非常有效的解决方案。
而不是使用" UI注册表跟踪所有UI"我创建了一个Proxy
对象,并用代理注册表替换了UI注册表。
为具有任何可视表示的每个对象创建Proxy
对象。它本身扩展QObject
并实现一个接口来访问底层Object
的属性,将它们包装在Qt样式属性中。
然后Proxy
对象被用作每个UI
的属性来读取和写入基础Object
属性,因此它可以自动运行"对于可能引用特定代理的每个UI。
这意味着不需要为每个UI
跟踪每个特定Object
,而只需通过计算引用它的UI数量来管理Proxy
的生命周期。< / p>
我还设法通过添加单个位hasProxy
标志(从其他标志中留下一些空闲位)来消除所有不会产生结果的查找,当标记为每个对象切换时代理被创建或销毁。这样在实际的Object
成员中,如果不使用&#34; blind&#34;数据例程,如果这样查找代理并通过它操纵对象。这将注册表查找限制为仅实际获得结果的少数注册表,并消除了大量非常徒劳的内容,只是为了意识到该对象根本没有可视化表示。
简而言之,总结一下先前设计的改进:
注册表现在要小得多,因为必须存储对象本身的指针和所有关联UI的向量,我现在为Proxy
的8个字节 - 指向对象的指针和任意数量的相关用户界面的计数器
通知是自动的,只需要通知代理,它会自动通知所有引用它的用户界面
以前赋予用户界面的功能现在已移至代理并在所有用户界面之间共享,因此用户界面本身更轻松,更易于实施,事实上我已经不必专门化一个独特的用户界面了。每个对象类型QQuickItem
能够使用通用QML Item
,而无需为UI实现和编译任何本机类
以前我必须手动管理的东西,实际的通知和负责它们的对象现在都是自动管理的
内存使用和CPU周期的开销大大减少了。之前的解决方案牺牲了CPU时间以减少相对于原始设计的内存使用量,但新设计消除了大部分CPU开销并进一步降低了内存使用量,并使实现变得更加容易和快捷。
它就像吃蛋糕一样吃了:)。