I currently develop a fairly large application which, amongst other things, calculates mathematical problems. Calculations are made in classes, let’s call them A and B, which have some random final attributes and a (unique) final int id as instance variables.
I want to be able to run the program in a test mode, where in each execution, the random variables are exactly the same and allow me, for example, to compare the results with hand-made calculations, using Junit tests. Obviously, I don't want to re-calculate my sample solutions after every code change (for example, if an earlier access to the prng is inserted which would shift all random numbers).
Note that I currently use Java.util.Random as prng, but am open to suggestions.
The question is now: How should I structure the instantiation and accessing of the prng? To point out the problem, note that following would be very bad approaches:
- I cannot make it a singleton and access from everywhere, as then, the random numbers within the classes would depend on the order of instantiation.
- I obviously cannot instantiate a new Random(seed) with a hardcoded seed, as the numbers would not be different if the programm is run multiple times (outside of test mode).
I came up with the following solution (largely based on this answer), but not identical, as the programming language and test seed generation is different.
public class PRNGeneratorGenerator{
//Make class a singleton
private PRNGeneratorGenerator instance;
private PRNGeneratorGenerator() {}
public PRNGeneratorGenerator getInstance(){
if (instance == null) instance = new PRNGeneratorGenerator();
return instance;
}
//RandomNumberGenerator-Methods and Attributes
private boolean isTestMode = false;
private Random seedRng = new Random();
public void setTestMode(boolean testMode){
isTestMode = testMode;
}
public Random getPseudorandomNumberGenerator(long testSeed){
if(isTestMode) return new Random(testSeed);
return new Random(seedRng.nextLong());
}
}
The classes (named A and B above) with the final random numbers would then look as follows:
public class A{
private final static long CLASS_SEED = 872349;
private final int randomNumberOne;
private final int randomNumberTwo;
private final int id;
public A(int id){
this.id = id;
long testSeed = CLASS_SEED + id;
Random rnd = PRNGeneratorGenerator.getInstance().getPseudorandomNumberGenerator(testSeed);
randomNumberOne = rnd.nextInt();
randomNumberTwo = rnd.nextInt();
}
}
In the test mode, I would call PRNGeneratorGenerator.getInstance().setTestMode(true)
before starting any instantiations.
Is this a good way to solve my problem in java or are there any downsides of this approach? I have read a number of similiar questions, but have found no equivalent ones which answers my question. Thanks in advance for your answer.
Aucun commentaire:
Enregistrer un commentaire