ServiceLocator和开/关原则 [英] ServiceLocator and the Open/Closed Principle

查看:88
本文介绍了ServiceLocator和开/关原则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想:


  1. 让需要他们的所有课程都看到所需的一般服务,

  2. 最少的样板,

  3. ,而不会牺牲可测试性!

一个小项目,我认为DI可能是过度的,但也许我错了?无论如何,我一直专注于Martin Fowler所描述的 ServiceLocator模式



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

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

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

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

然而,我也希望这个模型对象的可见性级别(如上面的fooModel),因为它们从几个不同的地方访问,不需要有多个实例。



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



为了满足OCP,我可以使用动态服务定位器(也在Fowler的页面上描述),但是我并没有完全按照他的理由出售,即不够明确。 p>

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

  fooItem1234 = FooModel :: findById(1234); 

我喜欢这个,因为它是零样板。我可以创建一个新的模型类,并从任何地方开始使用单行。但是现在的模型依赖于Locator找到它的数据库连接,我不知道我有什么感觉。一个,如果我需要在单独的数据库连接上打开两个fooModels,这将是一个混乱和/或不可能的。也就是说,我实际上并不需要这样做,所以这个选项似乎有点诱人。



最后还有DI。但是像上面所说的那样,我认为这个小项目可能太多了。



结论:我有点困在这里,并且会感谢大家的一些建议StackOverflow!

解决方案

为什么你认为DI对你的项目来说太过分了?像构造函数注入的DI模式比Service Locator(我认为是反模式)更简单和更干净。



我认为服务定位器成为一种反模式,因为它对API的用户完全不透明,依赖关系需要到位;因此,可以在服务定位器抛出的上下文中轻松地调用对象上的方法,而且API完全不用说这样。



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


I'd like to:

  1. Make commonly required services visible to all classes that need them,
  2. with a minimum of boilerplate, and
  3. without sacrificing testability!

It's a small project and I think DI might be overkill, but maybe I'm wrong? Anyhow, I have been focusing on the ServiceLocator pattern as described by Martin Fowler

In a client class' constructor, I have something like this:

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

Then the rest of the class' methods access the service through those member attributes, e.g.:

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

However I would also like this level of visibility for "model" objects (like fooModel above) because they are accessed from several different places and there is no need to have more than one instance.

So my initial thought was to extend Locator to have a ::getFooModel() but now it seems I'm violating the Open/Closed Principle, since I'll have to modify Locator every time I introduce a new model class.

To satisfy OCP, I could use the Dynamic Service Locator (also described on Fowler's page) however I'm not totally sold on this for the same reasons as him, i.e. it's not explicit enough.

Another solution would be to just make all my models' methods static. So:

fooItem1234 = FooModel::findById(1234);

I like this because it's zero boilerplate. I can just create a new model class and start calling it from anywhere with a single line. But now the model depends on Locator to find its DB connection and I'm not sure how I feel about that. For one, if I ever needed to have two fooModels open on separate database connections, it would be a mess and/or impossible. That said, I don't actually need to do that currently so this option seems a little tempting.

Finally, there's DI. But like I said above I think it might be too much for this little project.

Conclusion: I'm a little stuck here and would appreciate some advice from the gurus of StackOverflow!

解决方案

Why do you think that DI is overkill for your project? DI patterns such as Constructor Injection is way simpler and cleaner than Service Locator (which I consider an anti-pattern).

I consider Service Locator to be an anti-pattern since it is totally opaque to the user of the API which dependencies need to be in place; thus, one could easily invoke methods on your objects in a context where the Service Locator would throw, and the API gives you absolutely no clue that this is the case.

You don't need a DI Container to use DI. If just have a simple project, you can use what is known as Poor Man's DI where you wire up dependencies manually.

这篇关于ServiceLocator和开/关原则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆