Essentially this is a service locator or service factory. You may even call it a dependency injection container. That in itself is perfectly fine. It's great in fact. The problem with it is that you call it statically! You should be injecting your dependency injection container into your class:
class Foo {
protected $container;
public function __construct(Container $container) {
$this->container = $container;
}
public function addTitle() {
$this->container->getServiceX()->doIt();
}
}
There, now you're fully dependency injected and decoupled.
With a statically coupled call, you can still get into situations you were trying to avoid with a dependency injection container in the first place. What if you need to inject one class with service X and a second class with a slightly differently configured instance of service X, but you're statically calling the same container which can only hold one copy of service X? You're solving this by decoupling the static call to your container and allowing a differently configured container to be injected.