drgbpq5930 2009-12-14 06:04
浏览 47
已采纳

ServiceLocator和开放/封闭原则

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!

  • 写回答

2条回答 默认 最新

  • duanchi5078 2009-12-14 07:15
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题