注册表模式:使用还是不使用

5
我考虑在应用程序中使用注册表模式来存储一些窗口和面板的弱指针。 应用程序的一般结构如下图所示。
应用程序有一个MainFrame顶级窗口和几个子面板。 可以有许多基于TabPane类型的选项卡。 我需要从所有的TabPane选项卡引用ParamsPane面板,因此需要将指向ParamsPane对象的指针存储在某个地方。 有很多选项,但最明显的是(1)将指针存储在应用程序单例对象中或(2)创建一个简单的注册表类。 类似于:
class Registry {
public:
    static MainApp* application;
    static MainWindow* mainWindow;
};

这是一种好的实践吗?这种方法的好处和注意事项是什么?

2
很抱歉,我无法帮助你,但是因为这张漂亮的图片,我给你点赞。 - TonyK
你的Registry类是一个完整的示例,还是有一些缺失的成员? - Robert Harvey
@Robert 是的,它已经完成了。但是它将会通过更多指向窗口、面板和对象的指针进行扩展。 - ezpresso
啊,我明白了。那就是我认为缺失的部分。 - Robert Harvey
这个Google Tech Talk对这个概念持否定态度。他们称之为“服务定位器”,并在大约9分钟的时候讨论了它:http://www.youtube.com/watch?v=RlfLCWKxHJ0 - cgmb
3个回答

2
这取决于您为什么要引用ParamsPane。我可以想到两个原因和两种不同的解决方案。 您想更新ParamsPane中的数据,因为TabPane中的数据发生了变化。 如果这些数据与视图完全分离,那么您应该将其分离。这意味着遵循模型-视图-控制器模式。 ParamsPaneTabPane实例都可以单独访问模型。因此,两者之间没有直接引用。 无论数据如何,两者之间存在一些强链接。 如果前面提到的点不相关,并且两个面板之间存在非常强的链接,您可以考虑编写一个特定的TabPane类,该类存储对ParamsPane类的引用。
我认为这两种解决方案都比单例或“注册表”方法更好。请注意,我以前没有听说过这种模式,但我相信我理解了它的意图。有关全局状态对象(更具体地说是单例)为什么是一种不好的做法的更多信息可以在这里找到

感谢您的回复!让我解释一下应用程序的一些细节。ParamsPane 用于显示连接到 PC 的 USB dongles 列表。TabPane 用于对所选 dongle 进行操作。当选择/打开/关闭 dongle 时,应通知 TabPane。TabPane 实例由 NoteBook 对象创建,因此它没有给 ParamsPane 对象指针。当创建 TabPane 时,它需要一个指向 ParamsPane 对象的指针,以便能够订阅 ParamsPane 发出的事件。这就是注册表的作用! - ezpresso
@ezpresso:看起来你需要MVC。我相信,"当选择/打开/关闭Dongle时"将成为你的模型。 - Steven Jeuris

0
从可测试性的角度来看,使用注册表模式可能不是一个好主意。引用自this article
单元测试基于这样一个假设:您正在测试没有依赖关系的小型离散代码单元。这要求开发人员尽力消除依赖关系或以使依赖关系中和为贡献者对被测试单元的失败。在PHP 5中,对象在分配时不会被复制;相反,它们在哈希表中的地址被复制。这意味着如果您从注册表中检索对象,然后修改它,那么从注册表中进行的每个后续检索都将反映该修改。
这造成的重大问题是它阻止了您测试离散的代码单元。现在,测试失败的变量不再只有一个,而是两个:正在测试的代码单元和从注册表中检索到的对象。任何时候存在多个失败可能性时,单元测试的有效性就会降低。

我不确定我相信这个论点。文章摘录所描述的问题(注册表中值的持久性)可以使用另一个模拟对象来简单地抽象掉。这确保了使用注册表的代码的可测试性。然后,您只需要测试注册表本身以确保它正确地保留值。如果 PHP 的某些特性阻止了这种情况的发生,则这是语言的问题,而不是注册表模式的问题。 - Robert Harvey

0

你的Registry类和Singleton是全局变量的面向对象方式。建议将Params Pane放在MainFrame中,并将其作为引用传递给选项卡窗格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接