ServiceLocator和开放/封闭原则

时间:2009-12-14 06:04:05

标签: php design-patterns oop dependency-injection

我想:

  1. 使所有需要它们的类可以看到通常需要的服务,
  2. 使用最少的样板,
  3. 不牺牲可测试性!
  4. 这是一个小项目,我认为DI可能有点矫枉过正,但也许我错了?无论如何,我一直专注于ServiceLocator pattern as described by Martin Fowler

    在客户端类的构造函数中,我有类似的东西:

    this->db = Locator::getDb();
    this->log = Locator::getLogger();
    

    然后,其余的类'方法通过这些成员属性访问服务,例如:

    this->fooModel = new fooModel(this->db);
    fooItem1234 = this->fooModel->findById(1234);
    

    但是我也希望“模型”对象(如上面的fooModel)具有这种级别的可见性,因为它们可以从几个不同的位置访问,而且不需要有多个实例。

    所以我最初的想法是将Locator扩展为::getFooModel(),但现在看来我违反了开放/封闭原则,因为每次引入新的模型类时我都必须修改Locator。

    为了满足OCP,我可以使用动态服务定位器(也在Fowler的页面上描述)但是我出于与他相同的原因并没有完全出售,即它不够明确。

    另一个解决方案是让我所有模型的方法都是静态的。所以:

    fooItem1234 = FooModel::findById(1234);
    

    我喜欢这个,因为它是零样板。我可以创建一个新的模型类,并从任何地方开始用一行来调用它。但现在该模型依赖于Locator来找到它的数据库连接,我不确定我对此的看法。首先,如果我需要在不同的数据库连接上打开两个fooModel,那将是一团糟和/或不可能。也就是说,我实际上并不需要这样做,所以这个选项看起来有点诱人。

    最后,还有DI。但就像我上面所说的那样,我觉得这个小项目可能太过分了。

    结论:我有点卡在这里,非常感谢StackOverflow大师的一些建议!

2 个答案:

答案 0 :(得分:7)

为什么你认为DI对你的项目来说太过分了?诸如构造函数注入之类的DI模式比Service Locator(我认为是反模式)更简单,更清晰。

我认为Service Locator是一个反模式,因为它对API的用户完全不透明,需要依赖于它们;因此,可以在服务定位器抛出的上下文中轻松调用对象上的方法,而API绝对不会让您知道这种情况。

您不需要DI容器来使用DI。如果只是一个简单的项目,你可以使用所谓的穷人的DI 来手动连接依赖项。

答案 1 :(得分:3)

  

......并且不需要有多个实例。

你正在混合苹果和橘子。事实上,您只需要一个类的一个实例用于应用程序,这与使该实例全局可用是一个好主意并不是一回事。使用DI,您不会更改基数 - 仍然只有一个实例。您更改的是处理所述实例的变量范围。有区别。