The service locator behavioral pattern allows you to make use of an interface without knowing what class implements the interface.
This design pattern shares many aspects with the factory creational pattern. Both patterns allow you to use an interface without knowing exactly what class implements the interface. But while the factory design pattern is more focused on creating instances, this pattern is more focused on locating instances that already exist.
Maybe you have some code that handles logging and you use this code throughout your application. You’re not going to want to pass a logging instance to every method you call so that means a lot of places in your code that will need some way to find a logger. Without this design pattern, you might consider making the logger a singleton. But this requires that your code know exactly which singleton to use to get to the logger.
Instead of going directly to the logger, consider instead asking another class for the logger. This other class will be the service locator. And, yes, this means that you just traded one singleton for potentially another singleton. The point is though that your code is no longer coupled in all those places to a specific logger. It’s now coupled to a specific service locator. It uses the service locator to ask which logger it should use.
This gives you the ability to easily swap one logger for another one. You’ll still have problems if you want to swap out one service locator for another one. You’ll probably want to avoid doing that. And asking another service locator for a service locator is also a bad idea. Just stick with a single service locator and let it help you manage the various services needed though your application.