简体   繁体   中英

Converting currency using exchange rate

I have written a class to provide two utility functions on Monetary data. It is workingn fine but I would like to know if i can improve it any way? What I read was BigDecimal should be used when working with currency as precision is imiport.

public class Money {

/**
 * @param Currency type
 * @param Amount to convert
 * @return BigDecimal Converted currency in Euros (EUR) 
 */
public static BigDecimal convertCurrencyToEUR(BigDecimal inValue, String inCurrency) {
    /*Exchange Rates:
    GBP -> USD  = 1.654
    CHF -> USD  = 1.10
    EUR -> USD  = 1.35
    GBP = 1.654/1.35 EUR
    CHF = 1.10/1.35 EUR*/

    try{
        BigDecimal usd_factor = new BigDecimal("1.35");
        BigDecimal gbp_factor = new BigDecimal("1.654");
        BigDecimal chf_factor = new BigDecimal("1.10");

        BigDecimal gbp_eur_rate = gbp_factor.divide(usd_factor, 5, BigDecimal.ROUND_HALF_UP);
        BigDecimal chf_eur_rate = chf_factor.divide(usd_factor, 5, BigDecimal.ROUND_HALF_UP);


        if(inCurrency.equalsIgnoreCase("GBP")){
            BigDecimal eur = inValue.multiply(gbp_eur_rate);
            eur = eur.setScale(5, BigDecimal.ROUND_HALF_UP);
            return eur;

        } else if (inCurrency.equalsIgnoreCase("CHF")) {
            BigDecimal eur = inValue.multiply(chf_eur_rate);
            eur = eur.setScale(5, BigDecimal.ROUND_HALF_UP);
            return eur;
        } else {
            System.out.println("Unhandled Currency");
            return null;
        }
    }catch(ArithmeticException e){
        System.out.println("Arithmetic exception occoured: "+e);
        return null;
    }
}

/**
 * @param companyDataList
 * @return BigDecimal Average amount in Euros (EUR) 
 */
public static BigDecimal calculateAverageAmount(List<CompanyData> companyDataList) {
    try{
        BigDecimal result = new BigDecimal("0");

        for (CompanyData companyData : companyDataList) {
            result = result.add(companyData.getAmount());
        }
        result = result.divide(new BigDecimal(companyDataList.size()+""), 2, BigDecimal.ROUND_HALF_UP);
        return result;

    }catch(ArithmeticException e){
        System.out.println("Arithmetic exception occoured: "+e);
        return null;
    }
}

}


**Update - ** After a suggestion to use a factory pattern this is how it looks.

CurrencyFX

public interface CurrencyFX {

BigDecimal usd_factor = new BigDecimal("1.35");     //static final variable available in all
                                                    //implementations
BigDecimal convertCurrencyToEUR(BigDecimal inValue) throws ArithmeticException;

}

GBPCurrencyFX

public class GBPCurrencyFX implements CurrencyFX{

@Override
public BigDecimal convertCurrencyToEUR(BigDecimal inValue) {
    BigDecimal gbp_factor = new BigDecimal("1.654");
    BigDecimal gbp_eur_rate = gbp_factor.divide(usd_factor, 10, BigDecimal.ROUND_HALF_UP);

    BigDecimal eur = inValue.multiply(gbp_eur_rate);
    eur = eur.setScale(5, BigDecimal.ROUND_HALF_UP);
    return eur;
}

}

CurrencyFXFactory

public class CurrencyFXFactory {
//use getInstance method to get object of type CurrencyFX 
   public static CurrencyFX getInstance(String currency){
      if(currency == null){
         return null;
      }     
      if(currency.equalsIgnoreCase("GBP")){
         return new GBPCurrencyFX();
      } else if(currency.equalsIgnoreCase("CHF")){
         return new CHFCurrencyFX();
      } 
      return null;
   }

}

An improvement i can see is to attempt to use a factory pattern along with Polymorphism.

Have an interface called: CurrencyFX Have for each currency its own class, example : GBPCurrencyFX

Then have the factory return an instance of the currency you want to calculate. Remember, each class will have all the variables needed for the calculation. You can alsoconsider having a parent abstract class if Currency fx rate calculation will be common for all currencies.

This will follow the Open/closed principle (avoiding if/else chain), thus providing extensibility to your application.

Finally you can have code as shown below

CurrencyFX = CurrencyFXFacotry.getInstance("GBP");
BigDecimal eur= currencyFX.calculate();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM