2009-12-14 23 views
5

我想:服务定位和打开/关闭原则

  1. 使通常需要可见到需要它们的所有类,
  2. 用最少的样板,并
  3. 服务,而无需牺牲可测性!

这是一个小项目,我认为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)。

所以我最初的想法是扩展定位器有一个::getFooModel(),但现在看来我违反了打开/关闭原则,因为每当我引入一个新的模型类时,我将不得不修改定位器。

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

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

fooItem1234 = FooModel::findById(1234); 

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

最后,还有DI。但正如我上面所说,我认为这个小项目可能太多了。

结论:我有点卡在这里,并希望从StackOverflow的大师的一些建议!

回答

7

为什么你认为DI对于你的项目来说是过分的? DI模式,如构造函数注入比服务定位器(我认为是反模式)更简单,更清洁。

我认为服务定位器是一种反模式,因为它对API的用户来说是完全不透明的,这些依赖需要到位;因此,可以在服务定位器抛出的上下文中轻松地调用对象上的方法,并且API绝对不会知道情况如何。

您不需要DI容器来使用DI。如果只有一个简单的项目,您可以使用称为Poor Man的DI,您可以手动连接相关性。

+0

是的我的意思是使用一个容器,当我说我认为DI会矫枉过正,对不起。并感谢您的答案!当你说Constructor Injection你说我应该把我的dbconn和logger对象传递给依赖它们的类的构造函数吗?如果是这样,这实际上是我在做什么。然后,出于某种原因,我决定不得不将记录器添加到每个类的构造器原型中。但是现在你已经让我思考了,它似乎比我一直试图用这个ServiceLocator做的事情更有意义。 – oops 2009-12-14 09:47:56

+1

很酷。那么你通常最终要做的就是堆叠或包装依赖关系。您可能会有很多低级别服务,但您通常可以将其中的两个或三个包装在有意义的对象中,然后只注入其中的一个,而不是三个底层服务。您可以多次重复此操作,因为您希望为各个类保留相关性的数量。 – 2009-12-14 10:01:45

+0

如何将不完全相关的东西堆叠/包装(比如上面例子中的DBconn和logger)到一个名为“config”的对象中,或者是那种糟糕的形式? – oops 2009-12-14 11:06:40

3

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

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