Service locators allow you to remove required data from an interface of an object and instead get these data from a secondary object - the service locator.

We normally have direct dependency declarations in APIs:

    class A(data1: B, data2: C)

Compare this to using a service locator:

    class A(locator: L)
        data1 = locator.locate_data1();
        data2 = locator.locate_data2();
Where code internal to the A acquires B and C from the locator.


The biggest drawback with a service locator is that we now make dependencies implicit. Depending on whether your locator default-constructs locatables on non-existence or not, your program can also start failing dynamically instead of statically.


This pattern is useful if we need provide dependencies to a heterogeneous set of classes all with their own peculiar dependencies, while these classes are all created in a uniform way. An example is providing input data to a set of heterogeneous types.
    let v: Collection<dyn SomeInterface> = ...;

    let locator = ...;

    for a in v {