views:

77

answers:

3

I'm writing an interactive fiction game in java from scratch. I'm currently storing all of my game object references in a hashmap in a singleton called ObjectManager. ObjectManager has a function called get which takes an integer ID and returns the appropriate reference. The problem is that it returns a BaseObject when I need to return subclasses of BaseObject with more functionality.

So, what I've done so far is I've added a getEntity function which returns BaseEntity (which is a subclass of BaseObject). However, when I need the function to return to an object that is a subclass of BaseEntity that has added, required functionality, I will need to make another function. I know there is a better way, but I don't know what it is. I know very little of design patterns, and I'm not sure which one to use here. I tried passing 'class' as a parameter, but that didn't get me anywhere.

public BaseObject get(int ID){
    return (BaseObject)refMap.get(ID);
}

public BaseEntity getEntity(int ID){
    return (BaseEntity)refMap.get(ID);
}

Thanks, java ninjas!

+2  A: 

I would discourage you from proceeding with this design.

Google is eradicating singletons from their Java code base; maybe it's a good idea for you, too.

It sounds like you're trying to do something that's been done well by Spring's ApplicationContext. You're trying to write a configurable, flexible object factory. It's been done. I'd look into dependency injection engines like Spring and Guice. Even if you decide not to use them, perhaps they can offer some design inspiration.

The best you can do is return an Object and cast.

duffymo
That link is for a C++ parser for algebraic andlinear equations!
David Relihan
Ooops, wrong value in the paste buffer. Let me fix it.
duffymo
I will definitely keep this in mind, but I'm just starting out as a programmer, so keeping things simple is my priority for now. When I finish this project, I'll see if I can go back and redo it without singletons.
Robert
+2  A: 

Use a generic return type if you have a Java 5 runtime:

public <Entity extends BaseEntity> Entity getEntity(int ID){
    return (Entity)refMap.get(ID);
}
Arne Burmeister
This technique works perfectly. Now I only need one get function for all my objects. Thanks!
Robert
A: 

These two methods do the same thing; the second just saves the caller from making a cast. If you don't want to make a function for every subclass, then one answer is simply: don't. The caller has to cast but it works just as fine as what you're doing now, functionally.

You can dress up this same approach in generics:

<U> U get(int id, Class<U> clazz) {
  return (U) refMap.get(id);
}

But it doesn't save the caller much, since it just passes a Class object instead of casting.

If you're not wiling to make the caller do this work, you need to write those specialized methods then.

Sean Owen