1

我正在开发一个跨平台的 C++ 数据模型,其中包含近 1,000 种不同类型的数据项(但 < 100 种不同的数据结构/类)。为了处理模型到控制器的消息(即通知控制器某些数据项已更改),我正在考虑使用 boost:signals2。我认为这将有助于创建一个统一的观察者模式,该模式在不同的操作系统平台上保持不变。最初的实现是在 Mac OS / IOS 上,随后的 UI 是在 .net 和 unix 上开发的。

问题:

1)为了建立数据模型的观察,控制器应该连接什么类型的对象到信号2对象/插槽?对于观察到的每个数据项,控制器中是否应该有特定的功能/方法/选择器?这些函数应该是 C、C++ 还是 Objective-C/C++ 函数?

2) 信号应该具有什么级别的粒度?每个数据项都应该有自己的吗?或者模型对相关结构/记录的管理是否应该为每种类型的结构/记录维护一个信号?例如——应用程序偏好是否应该为所有偏好数据提供一个信号——传递关于哪些数据项被更改的信息?

3)发送信号(或接收信号的槽)的过程是否应该在单独的线程中执行?

4) 我知道 Cocoa 有自己的 Key-Value Observing 系统。但是这样的系统是否有利于与模型的基于信号 2 的观察者范式相结合 - 还是只是多余的?

更新:

关于实际 signal2 对象(不是观察者)的“粒度”,我认为每个文档有一个,应用程序首选项一个可能是一个不错的起点。我的文档数据已经有了一个“关键”概念,因此可以概括常见的 UI 案例,其中 UI 组件与特定的模型数据项相关联。

4

1 回答 1

1

这个问题有很多方面,所以我会尽力解决。

为什么我们希望能够在 Objective-C 和 .NET 中观察一些东西?

我认为思考为什么我们要观察第四代语言的数据模型是有启发性的?除了解耦子系统,在某些情况下,我们还可以将 UI 界面元素直接绑定到数据模型,从而避免在控制器中编写大量代码。这在基于 .NET 的 WPF 应用程序和 MacOSX 上的 AppKit 中是可能的。iOS 上的 UIKit 机会较少。

元模型

首先要指出的是,您要定位的两个语言运行时(Objective-C 和 .NET)提供了围绕对象属性构建的观察者模式的语言级实现。如果您想在不编写数千行样板代码的情况下集成它们,您也需要这样做。

这强烈表明您的所有 C++ 模型类都需要从提供通用属性机制的元模型继承。最后是一种观察它们的机制。

另一种方法是在 C++ 中生成大量样板设置器/获取器,并绑定对象以在 .NET 和 Objective-C 中使用它们。

适配器

对于 .NET 和 Objective-C,您将设计一个通用适配器类,它使用反射来完成它们的脏活。在 Objective-C 的情况下,您可以通过重写方法NSObject来将属性集/获取消息转发到底层模型的属性机制上。我相信在 .NET 中,您可以使用反射将与模型中的属性相对应的属性注入到适配器中。

[旁白] IDL/ORM

当然,如果你有一个建立在元模型之上的数据模型,你还不如使用某种 IDL 或 ORM 来描述和自动生成大量的模型类?您正在处理的大量课程也表明了这一点。

观察者的粒度

就粒度而言,您可以做任何一种 - 这实际上取决于您的数据模型更改的方式以及 UI 需要对其做出反应的方式。Objective-C 中的 KVO 是围绕对象上命名属性的更改而设计的,但受到限制,因为观察者对它观察到的所有对象和属性都有一个单一的委托方法。然而,这只是您的 Objective-C UI 组件的问题。
与此集成绝对值得,除非您想为 C++ 和 Objective-C 之间的值更改事件编写大量适配器方法:请记住,虽然 C++ 和 Objective-C++ 之间存在免费互通,但 Objective-C++ 类可以' t 继承接口 C++ 类,你不能直接从 C++ 向 Objective-C 对象发送消息,而无需在 Objective-C++ 编译单元中进行桥接和一些讨厌的转换。
使用 .NET,您可能会使用中间托管 C++ 层进行各种类似的阴谋。

穿线

涉及多个线程的唯一明智的方法是将信号排队以在 UI 线程上进行处理。毕竟,如果在另一个线程中生成信号,您将需要稍后执行此操作以更新 UI。对应用程序的模型和视图/控制器部分使用单独的线程听起来像是死锁的秘诀。调试信号源也很困难,因为它会在另一个线程中消失很久。将所有内容集中在一个线程上,您的生活会容易得多。

于 2013-05-30T00:04:04.033 回答