tags:

views:

135

answers:

3

I have three classes interacting in an interesting way. One is a model class, and it has to be accessed by both of the other classes, so a single instance of it is kept as a member of each. Both of these classes interact with the model in different ways.

There are a couple of instances where the model object has to be completely thrown away and replaced with a new instance, and this complicates things. And these occasions arise in both of the viewing/controlling classes. So, either one of those classes has to be able to send a signal to the other saying "We need to coordinate and facilitate the replacement of our Model object with a new Model object." Right now I have code in class B to tell class A to construct a new Model and send it back, but now I need to handle the opposite situation, where the event arises in class A, and unfortunately class A does not have a reference to class B and probably shouldn't.

What's a good way to handle this?

Update: Sorry, folks, this can't be a singleton. Singletons are when you need to guarantee there's only one of something. That has nothing to do with any of the requirements I expressed above. This class is not a singleton and shouldn't be.

Update: Up till now, there has actually only been one instance of this Model class, but I had a vague suspicion I needed to allow for more, and I didn't want to limit myself by using the Singleton design pattern when that actually addresses different concerns from what I have. Turns out I was right: yesterday I received a new requirement and now I need support an arbitrary number of these. :) Don't limit yourself when you don't have to, and don't misuse design patterns for situations where they were not intended!

+5  A: 

You'll want an intermediary model layer, a model "holder" object that each of the two classes reference. The ModelHolder holds a reference to the model.

This ModelHolder should also support listeners, so when its model is thrown out, it can notify any listeners that the model has changed.

Sam Barnum
I completely agree. The holder is the owner of the model. It manages the lifecycle of the model including servicing requests from clients to request the model be swapped out with a new one. Clients can register a listener to be notified of changes (such as a new model).
Steve Kuo
I think I'm going with a modified version of this. ClassA is actually the ModelHolder, in a sense, so I just implemented a listener interface which ClassB will implement to be notified when there is a new Model object it should pick up.
skiphoppy
hm. huh? No need to expose the actual different models!Let the SuperModel send an "i am updated" to its listeners, when it has changed its internal representation.COmpare to how StatePattern works.
KarlP
+1  A: 

Ok, if you need to change the model (but not force) you can make a listener interface, and make both objects A and B implement it:

public interface ModelListener {

    public void modelChanged(Model newModel);
}

and at the proper time you can notify the listeners of the new model change. You can also have a list that holds all the registered listeners.

List<ModelListener> modelListeners = new ArrayList<ModelListener>();

    public void setNewModel(Model m) {
     for (ModelListener aListener : m.modelListeners)
      aListener.modelChanged(m);
    }

As always there are tradeoffs between simplicity and robustness. You might want to experiment with the levels you need for your own case.

Azder
I don't think this will work; I don't see how a static method in the Model class can direct instances of ClassA and ClassB to replace the contents of their model field.
skiphoppy
Model is not a singleton.
skiphoppy
Why is getNewModel() synchronized?
Steve Kuo
Well... its a bad example, deleted.
Azder
A: 

I encounter this design issue often in GUI projects (Swing, GWT). What I usually do is create a higher-level "State" model, which holds an instance of the object that is shared between 2 or more classes. State then has a ModelListener interface, which the other classes can implement to get notification of changes to the underlying model. State.setFoo() then fires ModelChanged events to the listeners, which respond accordingly.

Caffeine Coma