The service locator pattern is a design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong abstraction layer. This pattern uses a central registry known as the "service locator", which on request returns the information necessary to perform a certain task. Source: Wikipedia
I've noticed, that a lot of PHP frameworks are eagerly adopting new patterns like service locators recently. I wasn't really happy to see that, because service locators are introducing an other abstraction layer, which adds complexity and moves dependencies away from the source. Also errors are entirely moved into runtime. One could argue that everything happens in runtime with interpreted languages, but that is also not entirely true in this case.
I was asking myself how a more pythonic and lightweight version of a service locator would look like and came to this conclusion:
# cats.py from django.conf import settings class CatService(object): """This CatService gets you the best cats in town.""" def __init__(self, foo, bar): self.foo = foo self.bar = bar def get_cats(baz): # TODO: implement get_cats… pass my_cat_service = CatService(settings.FOO, settings.BAR) # views.py from cats import my_cat_service my_cat_service.get_cats("baz")
I assume, that we are in a Django application. In
cats.py we are defining a
CatService which might connect us to a web service to download lists of cat images. This service will be used in several places of our project, so we want it to be as reusable as possible. But keep im mind that this is just an example. Services in the service locator pattern could be anything and not just web services. In
cats.py we are also creating a
CatService object and assign it to the variable
my_cat_service. Done! The service is ready to be use.
In one of your views we might then import
my_cat_service which has a ready to use
CatService object. Easy, isn't it?
This has several advantages:
- Services can easily be modified and extended in one place and
- are very easy to test.
- Missing dependencies are noticed during compilation.
- Very lightweight implementation without additional complexity.
- Your IDE has at least a chance to find the object type of