以下代码来自教程(http://net.tutsplus.com/php/creating-a-php5-framework-part-1/),而不是我的.
我对这段代码有几个疑问......
该文章声称它正在使用"注册表设计模式"; 这是该行业设计的通用名称吗?
是否还有其他类似的模式,这将是一个更好的选择?
这种模式被认为是在MVC框架环境中实现的良好实践吗?
我只想弄清楚是否应该在我自己的MVC框架实现中使用这种设计模式.谢谢!
troelskn.. 25
该文章声称它正在使用"注册表设计模式"; 这是该行业设计的通用名称吗?
是的,但实施可能明显不同.基本上,注册表是共享对象的容器.在真正的基本版本中,您可以使用数组.因此,变量$GLOBALS
可以称为注册表.
是否还有其他类似的模式,这将是一个更好的选择?
注册表有两种变体.有全球注册表(这是最常见的,这是一个例子).还有一个本地注册表.本地注册表传递给需要它的对象,而不是通过全局符号(静态类,单例等)获得.本地注册表具有较低的耦合度,但也略微抽象,因此存在权衡.
您还可以进一步使用完全依赖注入,您可以将所有依赖项显式传递给需要它们的对象.在较大的应用程序中,这可能有点单调乏味.您可以将它与依赖注入容器耦合,该容器是一段"知道"哪些类具有依赖关系的代码.这比本地注册表更复杂,但耦合程度非常低.
这种模式被认为是在MVC框架环境中实现的良好实践吗?
这是常见的做法.判断是好还是坏.就个人而言,我愿意接受一些复杂性以换取去耦,但是ymmv.
该文章声称它正在使用"注册表设计模式"; 这是该行业设计的通用名称吗?
是的,但实施可能明显不同.基本上,注册表是共享对象的容器.在真正的基本版本中,您可以使用数组.因此,变量$GLOBALS
可以称为注册表.
是否还有其他类似的模式,这将是一个更好的选择?
注册表有两种变体.有全球注册表(这是最常见的,这是一个例子).还有一个本地注册表.本地注册表传递给需要它的对象,而不是通过全局符号(静态类,单例等)获得.本地注册表具有较低的耦合度,但也略微抽象,因此存在权衡.
您还可以进一步使用完全依赖注入,您可以将所有依赖项显式传递给需要它们的对象.在较大的应用程序中,这可能有点单调乏味.您可以将它与依赖注入容器耦合,该容器是一段"知道"哪些类具有依赖关系的代码.这比本地注册表更复杂,但耦合程度非常低.
这种模式被认为是在MVC框架环境中实现的良好实践吗?
这是常见的做法.判断是好还是坏.就个人而言,我愿意接受一些复杂性以换取去耦,但是ymmv.
我认为,一般来说,并没有真正的"糟糕模式".话虽如此,一些技术应该比其他技术更加谨慎使用,全球注册表的概念通常不够优雅.问题在于给定对象之间的依赖关系是通过基于名称的寻址来处理的,这类似于简单地使用全局变量,而不是通过提供依赖关系来实现策略的间接 - 这通常被称为依赖注入.
这如何影响软件的重用和灵活性实际上非常清楚.考虑各种请求处理程序,它与OAuth2提供程序集成以进行身份验证.如果定义具有定义良好的接口的对象以向此OAuth2提供程序发出请求,则可以通过创建实现相同接口的另一个对象来更改提供程序.
现在让我们说,为了讨论,你的第一个实现需要访问Facebook.但接下来的一周,你决定你也应该支持雅虎,雅虎实施OAuth2的方式比Facebook更接近规范,实际上在授权令牌请求中使用JSON而不是名称值对.最重要的是,有不同的URL和密钥对以及需要保留的东西.
好吧,如果您使用注册表模式或服务定位器模式按名称查找身份验证提供程序,那么您现在遇到了问题.您需要复制代码并对其进行微小更改,以便您可以同时支持这两个代码,或者找到另一个解决方案,例如传递密钥并在所有位置添加哈希表以查找所有这些元素并检测这些差异.同时,如果使用依赖注入,则可以简单地创建身份验证提供程序的另一个实现,该实现实现解析身份验证令牌的微小差异,并创建使用该对象并已经过测试的请求处理程序的新实例,然后部署它到一个新的位置.
间接节省了您的工作,减少了必要的代码量,最终使您的软件更便宜,更好,更快.
话虽如此,有时两种模式不能直接互换.比方说,您正在构建一种将事件处理程序附加到XML文档节点的框架.您可以使用XPath或JQuery的CSS选择器实现来描述XML文档中节点的位置.但是为了附加事件处理程序,您还需要引用一些代码.最好,你会引用一些对象的某种方法 - 好吧,没有给它命名就找不到这个"某个对象",所以现在你需要一个服务定位器,这样你就可以按名称查找了.但请记住,即使在这个例子中,没有任何规定名称必须是全局的.
在此处调用本地服务定位器或本地注册表是解决此类问题的合理解决方案.如果在同一个应用程序中可能有两个注册表实例,则有时可以减轻上述某些重用问题.