ServiceLocator for easy and central access to replaceable parts For a bigger project of mine, I needed a simple and extensible solution for easy access to replaceable Parts.

This example will show the usage:


Define an Interface, describing the replaceable part Eg: IReportSender
Define the concrete EMailReportSender and TelegramReportSender
Both will be implementing the IReportSender
On Startup (or anywhere else in the Application) add it to the ServiceLocator: 

ServiceLocator.getServiceLocator().addService(IReportSender.class, new EMailReportSender());

Anywhere else in the application get the Service and use it:  

IReportSender reportSender = ServiceLocator.getServiceLocator().getService(IReportSender.class);
reportSender.SendReport([...]);



And now the Code:

import java.util.HashMap;

public class ServiceLocator {

    private static ServiceLocator instance;
    private HashMap&lt;Class&lt;?&gt;, Object&gt; services;

    /**
     * Creates a new instance of the {@link ServiceLocator}
     */
    private ServiceLocator() {
        services = new HashMap&lt;Class&lt;?&gt;, Object&gt;();
    }

    /**
     * Gets the {@link ServiceLocator}
     * @return the current {@link ServiceLocator}
     */
    public static ServiceLocator getServiceLocator() {
        if (instance == null) {
            instance = new ServiceLocator();
        }

        return instance;
    }

    /**
     * Adds a service
     * @param clazz class of the defining interface
     * @param service instance of the actual implementation
     * @return &lt;code&gt;true&lt;/code&gt;, if the service was added, otherwise &lt;code&gt;false&lt;/code&gt;
     */
    public boolean addService(Class&lt;?&gt; clazz, Object service) {
        if (services.containsKey(clazz) || !clazz.isAssignableFrom(service.getClass())) {
            return false;
        }

        services.put(clazz, service);

        return true;
    }

    /**
     * Gets a service
     * @param clazz class of the defining interface
     * @param &lt;T&gt; defining interface
     * @return instance of the actual implementation
     */
    public &lt;T&gt; T getService(Class&lt;T&gt; clazz) {
        if (!services.containsKey(clazz)) {
            return null;
        }

        Object service = services.get(clazz);
        return clazz.cast(service);
    }

    /**
     * Removes a service
     * @param clazz class of the defining interface
     * @return &lt;code&gt;true&lt;/code&gt;, if the service was removed, otherwise &lt;code&gt;false&lt;/code&gt;
     */
    public boolean removeService(Class&lt;?&gt; clazz) {
        if (!services.containsKey(clazz)) {
            return false;
        }

        services.remove(clazz);

        return true;
    }

    /**
     * Removes all services
     */
    public void removeAllServices() {
        services.clear();
    }

}
You have some clean looking code there, but there's a huge problem with Service Locators. They're hidden dependencies. If I reference your class from elsewhere, I'm going to be really confused about the exceptions I'm going to get when I try to use it. 


  Where is this null EmailService exception coming from?! WTF???


It's much better to use proper constructor injection of dependencies. That makes it crystal clear what is needed to make your class work.