dimanche 2 décembre 2018

How do avoid cases when trying to make a report of a statistics class?

There is a statistics class that needs to accept certain set of objects that have an int value where we need to calculate average/median/highest/... from. These results should be outputted to a report of a various file types(txt/html/...).

Here is the Statistics class:

public class Statistics {

private IStatsCommand highestValue;
private IStatsCommand lowestValue;
private int median;
private int average;


public Statistics(List<IStatsCommand> commands){
    calculateAverage(commands);
    calculateMedian(commands);
    calculateHighestValue(commands);
    calculateLowestValue(commands);
}

public void calculateAverage(List<IStatsCommand> commands){

    int totalValue = 0;
    for(IStatsCommand command: commands){
        totalValue += command.execute();
    }
    this.average =  totalValue/commands.size();
}



public void calculateMedian(List<IStatsCommand> commands) {

    List<IStatsCommand> newCommands = commands;
    int median = 0;

    Collections.sort(newCommands, new Comparator<IStatsCommand>() {

        @Override
        public int compare(IStatsCommand command1, IStatsCommand command2) {

            return command1.execute() - command2.execute();
        }
    });

    int index = newCommands.size()/2;
    if (newCommands.size()%2 == 1){
        median = newCommands.get(index).execute();
    }
    else{

        median = (newCommands.get(index).execute() + newCommands.get(index - 1).execute())/2;
    }
    this.median = median;
}

public void calculateHighestValue(List<IStatsCommand> commands){
    IStatsCommand commandWithHighestValue = commands.get(0);
    for(IStatsCommand command: commands){
        if (command.execute() > commandWithHighestValue.execute()){
            commandWithHighestValue = command;
        }
    }
    this.highestValue = commandWithHighestValue;
}

public void calculateLowestValue(List<IStatsCommand> commands){
    IStatsCommand commandWithLowestValue = commands.get(0);
    for(IStatsCommand command: commands){
        if (command.execute() < commandWithLowestValue.execute()){
            commandWithLowestValue = command;
        }
    }
    this.lowestValue = commandWithLowestValue;
}

public IStatsCommand getHighestValue(){
    return this.highestValue;
}

public IStatsCommand getLowestValue() {
    return lowestValue;
}

public int getMedian() {
    return median;
}

public int getAverage() {
    return average;
}
}

Now I need to create a report from this file. I need to put some extra info from the highest and lowest object. These objects can be a range of things where different information needs to be extracted from, highly depending on the object. How do I create a report class that avoids checking the specific type of each of these IStatsCommand objects in the statistic class by using something like instance of.

I have tried passing a type to Statistics and then in the report class had functions toString(Statistics st, Type1 t1),toString(Statistics st, Type2 t2). But it cluttered the class a lot and didn't allow a lot of flexibility for other programmers. How would I improve my design for a better report class ?

Aucun commentaire:

Enregistrer un commentaire