4

I'm using Gson to deserialise Json into a model ApplicationModel. I want this Model to be a singleton so I can access it elsewhere in my application.

Now as Gson creates an instance of this class, I'm creating the singleton instance in a rather unconventional way. See below:

public class ApplicationModel {

    private static ApplicationModel instance;

    private GeneralVO general;

    protected ApplicationModel() {
        instance = this;
    }

    public static ApplicationModel getInstance() {
        return instance;
    }

    public String getVersionDate() {
        return general.getVersionDate();
    }
}

This is the way I create it and then reuse it later in the application:

InputStreamReader reader = new InputStreamReader(is);
ApplicationModel model1 = new Gson().fromJson(reader,ApplicationModel.class);

Log.i("MYTAG", "InputStream1 = "+model1.toString());
Log.i("MYTAG", "Date: "+model1.getVersionDate());
ApplicationModel model2 = ApplicationModel.getInstance();
Log.i("MYTAG", "InputStream1 = "+model2.toString());
Log.i("MYTAG", "Date: "+model2.getVersionDate());

This works as the getInstance() returns the same model but somehow this just doesn't seem right.

My question is 'is this a good way of going about it or is there a better solution???'

EDIT

A much better way of doing singletons is to use an enum with one INSTANCE element.

See this post for an explanation

Community
  • 1
  • 1
droppin_science
  • 481
  • 4
  • 14

1 Answers1

1

I suggest to instantiate your singleton instance on your Model, rather than instantiating it using constructor.

public class ApplicationModel {

    private static ApplicationModel instance; //= new ApplicationModel(); 
    //instantiating here is called an "Eagerly Instantiated"

    private GeneralVO general;

    private ApplicationModel() { 
    }

    public static ApplicationModel getInstance() {
        //instantiating here is called "Lazily Instantiated", using : 
        //if (instance==null) {                  --> Check whether 'instance' is instantiated, or null
        //    instance = new ApplicationModel(); --> Instantiate if null
        //}
        return instance;  //return the single static instance
    }

    public String getVersionDate() {
        return general.getVersionDate();
    }
}

By setting the constructor to private, you prevent the object from being re-instantiated by another class, to use the object, you will have to call the object with ApplicationModel.getInstance().

So if you want to set values, call ApplicationModel.getInstance().setterMethod(value), Why this is useful? if you want to track the change, you will only need to track the setter method. If you used constructors, you will have to track the constructors too.

Example :

// To SET the value:
// instead of ApplicationModel model1 = new Gson().fromJson(reader,ApplicationModel.class);
ApplicationModel.getInstance.setValue(new Gson().fromJson(reader,ApplicationModel.class);

// To GET the value :
ApplicationModel.getInstance.getValue();

The "Eager Instantiation" vs "Lazy Instantiation" :

  • Eager Instantiation is useful if you want an easy way to deal with Threads
  • Lazy Instantiation has better memory footprints

There's more than that, you can google it for more info, but I think this should be enough for you right now.

Hope this helps, and good luck ^^

Regards,

Reid

reidzeibel
  • 1,622
  • 1
  • 19
  • 24
  • 4
    I'm not sure this answers the question exactly. As GSON uses reflection it returns an instance of the class. If I wanted to `getInstance()` I would need to `setInstance(new Gson().fromJson(reader,ApplicationModel.class))` if I am reading you correctly, this would open up the opportunity to change the singleton instance. This makes this approach open to potential error no? If a user sets the instance to something else later for some reason the singlton suddenly is something new. I have stayed with my original implementation as this keeps the instance safe from potential external tampering... – droppin_science Dec 16 '13 at 17:10