It seems to me that this is often encountered in practice and I was wondering if there is a design pattern for the following:
Suppose I have a class that represents a card:
public class Hand {
private static Random rng;
private Rank rank;
private Suit suit;
public Hand() {
if (prng == null)
prng = new Random();
}
//more stuff
}
}
Every time I instantiate a Card, I want a random card. Doing it the above way wastes one comparison to null per instantiation. If I create a static field and allocate it in the deceleration:
private static Random rng = new Random();
a new Random object gets instantiated every time – also not very efficient.
If I pass the Random object into the constructor, I violate “tell, don’t ask.”
Perhaps there is another suggestion, but so far, I think the best way is the null check.
1
A constructor should be deterministic if possible, otherwise your code will be untestable. Have at least one overloaded constructor that can accept an RNG:
public Hand(Random prng) {
// more stuff
}
An argument-less constructor could give a default RNG, as in your design sketch. While a null
comparision isn’t that expensive and a new Hand
isn’t that common, you could just initialize the RNG with the class:
private static Random prng = new Random();
public Hand() {
this(prng);
}
This way, the RNG initialization is executed only once.
Otherwise, the quote about premature optimization applies…
2
If I create a static field and allocate it in the deceleration:
private static Random rng = new Random();
a new Random object gets instantiated every time – also not very efficient.
This is simply not true – it will create a single Random
when the class is initialized, that’s what static
means. Thus, it is the correct solution. But also note that Random
objects are pretty lightweight and there is no reason to be overly reluctant to create them, unless you’re doing it millions of times per second.