I have started a new project for credit management and I got to a point where I have to handle currency exchange. (example Euro -> Dollar) So I did a bit of brainstorming and got this:
- currencies are abstract, every new currency is an implementation of an interface
- built a rate class which stores an array list of pair< pair, double > (I was thinking of something like euro, dollar,1.14 -> the exchange rate of the euro to dollar is 1.14) and has some functionalities like: currency exchange rate storage, a finder for the right rate(it is a function that gets the current currency and the new currency as parameters and performs a search over the list, returning the appropriate currency) and a utility function which determines the index of a pair.
Now, I am thinking about performance. I believe that my design contains a bit of redundancy: if I have euro-to-dollar I have to have dollar-to-euro. Moreover, how efficient is my storage (array list of pair< pair, double >) for a higher number of entries (suppose 100k) and what alternatives do I have? I know there are lots of data structures and I really don't know what to pick.
Now, for the code:
conversion rates class:
package currency;
import javafx.util.Pair;
import loggers.ILogger;
import java.util.ArrayList;
public class ConversionRates implements IConversionRate {
private ArrayList<Pair<Pair<String, String>, Double>> conversionRates;
private ILogger log;
public ConversionRates(ArrayList<Pair<Pair<String, String>, Double>> conversionRates, ILogger log) {
this.conversionRates = conversionRates;
this.log = log;
}
@Override
public double find(ICurrency firstCurrency, ICurrency secondCurrency) {
log.add("Performing rate identification");
String first = firstCurrency.getId();
String second = secondCurrency.getId();
int index = searchPairs(first, second);
Pair<Pair<String, String>, Double> selectedPair = conversionRates.get(index);
double rate = selectedPair.getValue();
return rate;
}
private int searchPairs(String first, String second) {
Pair<String, String> pairContainingRate = new Pair<>(first, second);
for (int index = 0; index < conversionRates.size(); index++) {
if (conversionRates.get(index).getKey().equals(pairContainingRate)) {
log.add("Successfully found target " + first + "/" + second);
return index;
}
}
log.add("Failed to find target " + first + "/" + second);
return -1;
}
@Override
public void add(Pair<Pair<String, String>, Double> newRate) {
log.add("Added new rate " + newRate);
conversionRates.add(newRate);
}
@Override
public void update(ArrayList<Pair<Pair<String, String>, Double>> newRates) {
log.add("Updated rates");
conversionRates.clear();
conversionRates.addAll(newRates);
}
@Override
public void remove(Pair<Pair<String, String>, Double> redundantRate) {
log.add("Removed rate " + redundantRate);
conversionRates.remove(redundantRate);
}
}
ConversionRates interface:
package currency;
import javafx.util.Pair;
import java.util.ArrayList;
public interface IConversionRate {
double find(ICurrency euro, ICurrency newCurrency);
void add(Pair<Pair<String,String>,Double> newRate);
void update(ArrayList< Pair<Pair<String,String>,Double> > newRates);
void remove(Pair<Pair<String,String>,Double> redundantRate);
}
Currency interface:
package currency;
public interface ICurrency {
double convertTo(double amount, ICurrency newCurrency);
double convert(double oldCurrencyAmount, double conversionRateToNewCurrency);
String getId();
}
Currency implementation(I will list only the Euro as the euro is exactly the same):
package currency;
public class Euro implements ICurrency {
private String id;
private IConversionRate conversionRateFinder;
public Euro(String id, IConversionRate conversionRateBuilder) {
this.id = id;
this.conversionRateFinder = conversionRateBuilder;
}
@Override
public double convertTo(double amount, ICurrency newCurrency) {
double currentConversionRate = conversionRateFinder.find(this, newCurrency);
double newAmount = newCurrency.convert(amount,currentConversionRate);
return newAmount;
}
@Override
public double convert(double oldCurrencyAmount, double currentConversionRate) {
return oldCurrencyAmount*currentConversionRate;
}
public String getId() {
return id;
}
}
I would like to hear from you about the general design as well.