我想:服务定位和打开/关闭原则
- 使通常需要可见到需要它们的所有类,
- 用最少的样板,并
- 服务,而无需牺牲可测性!
这是一个小项目,我认为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的大师的一些建议!
是的我的意思是使用一个容器,当我说我认为DI会矫枉过正,对不起。并感谢您的答案!当你说Constructor Injection你说我应该把我的dbconn和logger对象传递给依赖它们的类的构造函数吗?如果是这样,这实际上是我在做什么。然后,出于某种原因,我决定不得不将记录器添加到每个类的构造器原型中。但是现在你已经让我思考了,它似乎比我一直试图用这个ServiceLocator做的事情更有意义。 – oops 2009-12-14 09:47:56
很酷。那么你通常最终要做的就是堆叠或包装依赖关系。您可能会有很多低级别服务,但您通常可以将其中的两个或三个包装在有意义的对象中,然后只注入其中的一个,而不是三个底层服务。您可以多次重复此操作,因为您希望为各个类保留相关性的数量。 – 2009-12-14 10:01:45
如何将不完全相关的东西堆叠/包装(比如上面例子中的DBconn和logger)到一个名为“config”的对象中,或者是那种糟糕的形式? – oops 2009-12-14 11:06:40