1

I have a class like so:

public class Contact {

    private static volatile Contact instance;

    private List<Item> contacts = new ArrayList<>();
    private Context context;

    public static Contact getInstance(Context context) {
        Contact localInstance = instance;
        if (localInstance == null) {
            synchronized (Contact.class) {
                localInstance = instance;
                if (localInstance == null) {
                    instance = localInstance = new Contact(context);
                }
            }
        }
        return localInstance;
    }

    public Contact(BaseAuthActivity context) {
        this.context = context;
        update();
    }

Here I create an instance of the class, synchronizing on the class property.

I have plenty of such classes in my project. Is there a way to create a base class, that would implement the getInstance method, so I don't need to keep this code in all my classes? I tried using generics, but with no luck. Maybe there's an example of what I try to achieve?

serg66
  • 1,148
  • 1
  • 17
  • 31

1 Answers1

0

One way of doing this is to hold a map from the Class object you want to instantiate and the the singleton instance you're using. Assuming that all your classes have a public constructor from a Context, you can use reflection to invoke it:

public class Contact {

    private static ConcurrentMap<Class<? extends Contact>, Contact> instances = 
        new ConcurrentHashMap<>();

    public static <T extends Contact> T getInstance
        (Context context, Class<T> clazz) {

        T instance = (T) instances.get(clazz);
        if (instance == null) {
            synchronized (clazz) {
                instance = (T) instances.get(clazz);
                if (instance == null) {
                    try {
                        Constructor<T> constructor = 
                            clazz.getConstructor(Context.class);
                        return constructor.newInstance(constructor);
                    } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
                        // log
                        return null;
                    }
                }
            }
        }
        return instance;
    }
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350