Grundlefleck
Grundlefleck

Reputation: 129327

Is there a commonly used OO Pattern for holding "constant variables"?

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:

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

Upvotes: 3

Views: 1160

Answers (4)

Grundlefleck
Grundlefleck

Reputation: 129327

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.

Upvotes: 2

alphadogg
alphadogg

Reputation: 12920

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.

Upvotes: 2

Christian Nunciato
Christian Nunciato

Reputation: 10409

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.

Upvotes: 0

Steve B.
Steve B.

Reputation: 57325

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):
}

Upvotes: 0

Related Questions