为什么使用Zend_Registry而不是Singleton模式?

时间:2011-09-12 13:38:01

标签: php zend-framework design-patterns

为什么我应该使用Zend_Registry而不是Singleton模式?

我的同事和我最近讨论过这件事。他的观点是我们应该将Zend_Registry用于所有一致的对象,但是我想使用单例模式,因为Zend_Registry只是做了同样的事情,但是被包裹了。

我遇到像这样的代码问题:

$list = Zend_Registry::get('database')->getList($sql);

由于数据库有可能不在Zend_Registry中。在延迟加载的情况下,我必须使用有关系统中特定对象的信息创建自己的注册表。就像数据库在加载时获取特定参数一样,它必须知道这一点。

我会使用getInstance,然后所有代码都将驻留在同一个对象中。这有意义吗?

2 个答案:

答案 0 :(得分:2)

即使你把你的问题称为或者,或者,我可以建议第三种选择吗?

我试图尽可能避免单身和Zend_Registry,因为它们实际上是全局的。当一段代码可以进入全局以太 - 通过调用单例或全局注册表 - 来获得它需要的东西时,它会创建一个隐藏的 - 或者至少是一个非显式的 - 依赖,这使得事情更难调试和单元测试。

相比之下,我尝试遵循依赖注入建议,将其解释为:“为组件提供所需的内容。不要让它找到它需要的东西。”

我发现对于我可能认为我需要注册表/单例 - 数据库连接,记录器等的大多数实体 - 我可以在Bootstrap创建它们,将它们存储在Bootstrap注册表中将它们注入我的控制器,通常在使用init()的{​​{1}}期间。只有控制器返回$this->getInvokeArg('bootstrap')->getResource('myResource')。然后,任何需要这些依赖关系的模型或服务都会通过构造函数或setter注入显式地由控制器传入它们。

我有时会退回的混合方法是使用针对这些依赖项的getter / setter来设计我的服务/模型类 - BootstrapgetDbAdapter(); setDbAdapter()getLogger()等等。来自全局注册表的getter延迟加载 - 无论是一些单例还是Zend_Registry,当它们不在我期望的范围内时抛出异常。从这个意义上说,它与你的建议相似。它确实违反了纯粹的依赖注入哲学。但至少getter / setter方法的存在明确地表明存在依赖关系并允许我模拟它或提供非默认实现。

答案 1 :(得分:1)

它适用于简单的博客或其他东西。否则你只会遇到一个数据库实例。从长远来看,这不是你想要的。您可能希望连接到其他服务器(将错误记录到中央数据库,从某人导入产品,......)或以不同用户身份连接(出于安全原因 - 您不希望您的API有权访问admin_users表,但你仍然需要连接到它来检查用户是否有效。)

你可以做一个通用的寄存器(My_Db_Admin,My_Db_ReadOnly,...),但这对我来说没什么意义。使用注册表,您不会遇到一个实例。您可以创建一个外部注册表并使用它一段时间然后将其删除;)