views:

333

answers:

4

I am working on a little pinball-game project for a hobby and am looking for a pattern to encapsulate constant variables.

I have a model, within which there are values which will be constant over the life of that model e.g. maximum speed/maximum gravity etc. Throughout the GUI and other areas these values are required in order to correctly validate input. Currently they are included either as references to a public static final, or just plain hard-coded. I'd like to encapsulate these "constant variables" in an object which can be injected into the model, and retrieved by the view/controller.

To clarify, the value of the "constant variables" may not necessarily be defined at compile-time, they could come from reading in a file; user input etc. What is known at compile time is which ones are needed. A way which may be easier to explain it is that whatever this encapsulation is, the values it provides are immutable.

I'm looking for a way to achieve this which:

  • has compile time type-safety (i.e. not mapping a string to variable at runtime)
  • avoids anything static (including enums, which can't be extended)

I know I could define an interface which has the methods such as:

 public int getMaximumSpeed();
 public int getMaximumGravity();

... and inject an instance of that into the model, and make it accessible in some way. However, this results in a lot of boilerplate code, which is pretty tedious to write/test etc (I am doing this for funsies :-)).

I am looking for a better way to do this, preferably something which has the benefits of being part of a shared vocabulary, as with design patterns.

Is there a better way to do this?

P.S. I've thought some more about this, and the best trade-off I could find would be to have something like:

public class Variables {
   enum Variable {
       MaxSpeed(100),
       MaxGravity(10)

       Variable(Object variableValue) {
          // assign value to field, provide getter etc.
       }
   }

   public Object getVariable(Variable v) { // look up enum and get member }

} // end of MyVariables

I could then do something like:

Model m = new Model(new Variables());

Advantages: the lookup of a variable is protected by having to be a member of the enum in order to compile, variables can be added with little extra code
Disadvantages: enums cannot be extended, brittleness (a recompile is needed to add a variable), variable values would have to be cast from Object (to Integer in this example), which again isn't type safe, though generics may be an option for that... somehow

+2  A: 

Are you looking for the Singleton or, a variant, the Monostate? If not, how does that pattern fail your needs?

Of course, here's the mandatory disclaimer that Anything Global Is Evil.

UPDATE: I did some looking, because I've been having similar debates/issues. I stumbled across a list of "alternatives" to classic global/scope solutions. Thought I'd share.

alphadogg
I don't need to limit the number of instances, nor do I need a global point of access. I'm looking for something which is better than both: what is essentially a runtime hashmap lookup; and a boring getter interface which would be extremely specific to this project, does that make sense? :)
Grundlefleck
It's the global, more particularly the static aspect I'm trying to avoid. I'd like to be able to say that there could be many instances of my model which share no run-time dependencies.
Grundlefleck
Then, you likely want something modeled like the Monostate.
alphadogg
I'd cancel the above comment, but I did want to say it was in reply to your first comment, before your second. Just in case you saw it...
alphadogg
+1 for c2 links.
Paul Morie
A: 

If you're just using java/IOC, why not just dependency-inject the values?

e.g. Spring inject the values via a map, specify the object as a singleton -

<property name="values">
    <map>
        <entry> <key><value>a1</value></key><value>b1</value></entry>
        <entry> <key><value>a2</value></key><value>b3</value></entry>
    </map>
  </property>

your class is a singleton that holds an immutable copy of the map set in spring -

private Map<String, String> m;

public String getValue(String s)
{
  return m.containsKey(s)?m.get(s):null;
}

public void setValues(Map m)
{
  this.m=Collections.unmodifiableMap(m):
}
Steve B.
The problem I have with the name->value map is that it does not have compile-time safety (I know what all the variables will be at compile time). A safer version is to map an enum member to a value, but enums have a static-y, un-extendable quality to them.
Grundlefleck
A: 

From what I can tell, you probably don't need to implement a pattern here -- you just need access to a set of constants, and it seems to me that's handled pretty well through the use of a publicly accessible static interface to them. Unless I'm missing something. :)

If you simply want to "objectify" the constants though, for some reason, than the Singleton pattern would probably be called for, if any; I know you mentioned in a comment that you don't mind creating multiple instances of this wrapper object, but in response I'd ask, then why even introduce the sort of confusion that could arise from having multiple instances at all? What practical benefit are you looking for that'd be satisfied with having the data in object form?

Now, if the values aren't constants, then that's different -- in that case, you probably do want a Singleton or Monostate. But if they really are constants, just wrap a set of enums or static constants in a class and be done! Keep-it-simple is as good a "pattern" as any.

Christian Nunciato
I want to be able to create two model instances, that both require different "constants" (constant in that they are final for the life of the model, but not constant to every model). I was looking for a polymorphic solution where the interface didn't have to define a getter for each variable...
Grundlefleck
... but I suppose defining a getter for each isn't so bad, it's safe and implementations can easily enforce that variables are final. I just wanted something a bit nicer than an immutable getter class, and it will do the job... but if there was something to learn I wanted to seize the opportunity
Grundlefleck
I get that, but what I don't get is why, if they're all constants defined at compile-time anyway, why you'd ever want multiple instances of them lying around. If the values are always the same, why use multiple instances at all?
Christian Nunciato
Yeah, it seems if you want the compile-time type checking, you'll need the typed accessors, which both enums and static constants, wrapped or otherwise, will get you.
Christian Nunciato
I think I didn't explain myself well. The values, their names, type etc are defined at compile time, the actual value for them are not. E.g. at compile time I know I want something called MaxGravity somewhere, but I don't know what it's numeric value will be, it may depend on something at runtime...
Grundlefleck
... though I think I may get what you mean now. Did you mean I have static/enum/constant things just to use as *accessors*? And what they're accessing is a value assigned by an implementation? That makes sense. P.S. my obsession with non-static things is just a challenge to myself :-)
Grundlefleck
Ok, I think I understand. Still, I still don't think there's a particular pattern for that per se -- what you want is really just an object with plain ol' getters and setters. That'd give you the multiple instances, compile-type type checking and the object-based interface you're after. I think. :)
Christian Nunciato
Out of curiosity, how will you be setting the values? Where will the "sort of constants" live before they get applied to the object containing them?
Christian Nunciato
That's partly why I found it hard to define what I meant - they could be from anywhere: config files; result of randomising; even user input. They can change before they get into the containing object, but once in they're unchangeable. Though now I think of it there may be more to immutability.
Grundlefleck
Yeah, it sounds like it wants to be a bunch of read-only getters, and maybe your constructor's left to retrieve and privately set all the member values somehow at runtime. Nevertheless it sounds you've got a solution you're happy with. :)
Christian Nunciato
+1  A: 

Thanks for all the time spent by you guys trying to decipher what is a pretty weird question.

I think, in terms of design patterns, the closest that comes to what I'm describing is the factory pattern, where I have a factory of pseudo-constants. Technically it's not creating an instance each call, but rather always providing the same instance (in the sense of a Guice provider). But I can create several factories, which each can provide different psuedo-constants, and inject each into a different model, so the model's UI can validate input a lot more flexibly.

If anyone's interested I've came to the conclusion that an interface providing a method for each psuedo-constant is the way to go:

public interface IVariableProvider {
    public int maxGravity();
    public int maxSpeed();
    // and everything else...
}

public class VariableProvider {
    private final int maxGravity, maxSpeed...;
    public VariableProvider(int maxGravity, int maxSpeed) {
        // assign final fields
    }
}

Then I can do:

Model firstModel = new Model(new VariableProvider(2, 10));  
Model secondModel = new Model(new VariableProvider(10, 100));

I think as long as the interface doesn't provide a prohibitively large number of variable getters, it wins over some parameterised lookup (which will either be vulnerable at run-time, or will prohibit extension/polymorphism).

P.S. I realise some have been questioning what my problem is with static final values. I made the statement (with tongue in cheek) to a colleague that anything static is an inherently not object-oriented. So in my hobby I used that as the basis for a thought exercise where I try to remove anything static from the project (next I'll be trying to remove all 'if' statements ;-D). If I was on a deadline and I was satisfied public static final values wouldn't hamstring testing, I would have used them pretty quickly.

Grundlefleck
*Mutable* static data is bad, because it causes unwanted side effects, but *immutable* static data (such as static final constants) is not bad. Also I avoid mutable static data, but in my current project there were two cases where it was unavoidable: http://dimdwarf.sourceforge.net/documentation
Esko Luontola
I don't think static final constants are bad, per se, but I don't see them as being pure OO. That doesn't mean to say I don't use them, as they're the most conventional, and what I'm doing just now is so (deliberately) over-engineered it almost proves their use... I just don't like 'em :-D
Grundlefleck
psst, you missed a couple closing parentheses in your second code block.
Paul Morie
Parentheses added, thanks Paul.
Grundlefleck