Java Singleton – MVC Design: Singleton in Model with Initialization

javasingleton

I've recently learned of MVC (model view controller) and am trying to refactor an existing program. I am in a situation where I'd like to have exactly one object of a particular class so it seemed evident that I should use a singleton. This singleton will be used to keep a hashmap of certain things. However this hashmap will have to be initialized when the singleton is created by reading nodes from a xml file and storing them as class objects.

Now my dilemma is:

  1. If I initialize the xml attributes (reading and converting to class objects), I'm effectively doing things in the model class that the controller should be doing, which is definitely not good.

  2. If I put the initialization method in a controller class, I would have to refer to a controller class from a model class, which does not conform to the MVC design.

  3. If I put the whole singleton in controller, then I'd have to look for the hashmap in the controller package, which defeats the purpose of having model classes.

  4. I can't pass a premade hashmap to the singleton as a parameter neither, because the constructor is private.. Well, I technically could, by giving it to the getInstance() method as a parameter, but it feels like a dirty way of fixing, since I now either pass null every time, or make another getInstance() method that doesn't accept a parameter.

Right now, my code is looking like this:

public class CategoryCatalog{

    private static CategoryCatalog categoryCatalog;
    private HashMap<CarOptionCategory, Set<ICarOption>> categoryOptionsMap;

    private CategoryCatalog(){
        categoryOptionsMap = new HashMap<CarOptionCategory, Set<ICarOption>>();
        initialize();
    }

    public static CategoryCatalog getInstance(){
        if(categoryCatalog == null){
            categoryCatalog = new CategoryCatalog();
        }
        return categoryCatalog;
    }

    private void initialize(){
        // TODO: xml
    }
}

Am I overlooking something or should I use a different approach?

Best Answer

You have to use the right tool for the right problem. MVC is used to separate the representation logic from routing request logic (controller) and business logic (the model).

For creating objects you should use Creational Patterns. Now, in my opinion,

If I initialize the xml attributes (reading and converting to class objects), I'm effectively doing things in the model class that the controller should be doing, which is definitely not good.

It's good if the classes are used by the model.

If I put the initialization method in a controller class, I would have to refer to a controller class from a model class, which does not conform to the MVC design.

Yep, don't do this because a low lever layer should not depend of a higher layer.

If I put the whole singleton in controller, then I'd have to look for the hashmap in the controller package, which defeats the purpose of having model classes.

This singleton is not a controller so don't do that too.

I can't pass a premade hashmap to the singleton as a parameter neither, because the constructor is private.. Well, I technically could, by giving it to the getInstance() method as a parameter, but it feels like a dirty way of fixing, since I now either pass null every time, or make another getInstance() method that doesn't accept a parameter.

Yep, you will break encapsulation here because the hash map is an invariant of your class and if you accept a hash map it means that the invariant can be overwritten, maybe accidentally.

In my opinion this singleton is some kind of factory that provides classes, if the classes are used by the model, then put this singleton in your model package. also take a look at Spring, it will do this for you in a nice way.

Related Topic