2010-06-08 20 views
4

這裏是一個小的貨幣轉換的代碼:如何在java中爲通用轉換器擴展此設計?

public enum CurrencyType { 

     DOLLAR(1), 
     POUND(1.2), 
     RUPEE(.25); 

     private CurrencyType(double factor) { 
      this.factor = factor; 
     } 
     private double factor; 

     public double getFactor() { 
      return factor; 
     } 

    } 

    public class Currency { 

     public Currency(double value, CurrencyType type) { 
      this.value = value; 
      this.type = type; 
     } 

     private CurrencyType type; 
     private double value; 

     public CurrencyType getCurrencyType() { 
      return type; 
     } 

     public double getCurrencyValue() { 
      return value; 
     } 

     public void setCurrenctyValue(double value){ 
      this.value = value; 
     } 

    } 

public class CurrencyConversion { 


    public static Currency convert(Currency c1, Currency c2) 
      throws Exception { 
     if (c1 != null && c2 != null) { 
      c2.setCurrenctyValue(c1.getCurrencyValue() 
        * c1.getCurrencyType().getFactor() 
        * c2.getCurrencyType().getFactor()); 
      return c2; 
     } else 
      throw new Exception(); 
    } 


} 

我想提高這個代碼,使其轉換不同的單位工作,例如:公斤到磅,英里公里,等等等等看起來像這樣的東西:

public class ConversionManager<T extends Convertible> { 


    public T convert(T c1, T c2) 
    { 
     //return null; 
    } 
} 

欣賞你的想法和建議。

回答

4

這是在我看來這是面向對象的方式。請注意,你也可以在數據類型上進行模板化,但是因爲它們可以表示任何標量單位,所以我在這裏只使用了雙精度。這提供了不同的度量單位之間的轉換處理,你問了一個很好的方式:距離,貨幣,質量等

public interface Metric { 
    public String getReferenceUnit(); 
} 

public class Distance implements Metric { 
    public String getReferenceUnit() { 
     return new String("Meters"); 
    } 
} 

public interface Units<T extends Metric> { 
    public double getToReferenceFactor(); 
} 

public class Kilometers implements Units<Distance> { 
    public double getToReferenceFactor() { 
     return 1000; 
    } 
} 

static <T extends Metric> double convert(Units<T> from, Units<T> to) { 
    return from.getToReferenceFactor() * (1.0/to.getToReferenceFactor()); 
} 
+0

謝謝你的回答。這裏有一個問題:getReferenceUnit()方法的重點是什麼? – Jay 2010-06-08 16:07:40

+0

這個想法是,每個度量都有一個參考單位,每個其他單位根據參考單位定義它自己。在你最初的例子中,參考單位是美元,而其他貨幣是以美元換算的因數。我在這裏添加了getReferenceUnit()函數,只是爲了說明距離參考單位是米,因此千米單位實現將具有1000個轉換因子。 – bshields 2010-06-08 17:42:04

1

在java中枚舉不幸的是不支持接口或超類(我想找出適當的原因)。

你可以做的是在你的枚舉類型(例如@Convertible)上聲明一個註解,並使用反射來訪問它的因子。這非常難看,你將無法在泛型中使用「T extends Convertible」表達式。

+0

是的,但事實上,當使用泛型一個不能延伸枚舉吮吸。使用自定義註釋是我想用作最後手段的東西。 – Jay 2010-06-08 12:29:19

1

下面是一個使用空心矩陣的通用轉換器,而不會傳遞閉包來結合已知轉換器。在這種情況下,將其轉換長度單位:

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

public class Converter { 
    private static final Map<String, Map<String, Double>> FACTOR_MAP 
      = new HashMap<String, Map<String, Double>>(); 

    public static double convert(String from, String to, double value) { 
     List<Step> stack = new ArrayList<Step>(); 
     stack.add(new Step(from, value)); 
     while (!stack.isEmpty()) { 
      Step s = stack.remove(0); 
      double val = s.value; 
      String source = s.unit; 
      if (source.equals(to)) { 
       return val; 
      } 
      Map<String, Double> map = FACTOR_MAP.get(source); 
      if (map != null) { 
       for (Map.Entry<String,Double> entry: map.entrySet()) { 
        stack.add(new Step(entry.getKey(), val*entry.getValue())); 
       } 
      } 
     } 
     throw new IllegalArgumentException("Cannot not convert from " + from 
       + " to " + to); 
    } 

    public static void registerFactor(String from, String to, double factor) { 
     putFactor(from, to, factor); 
     putFactor(to, from, 1.0/factor); 
    } 

    private static void putFactor(String from, String to, double factor) { 
     Map<String, Double> map = FACTOR_MAP.get(from); 
     if (map == null) { 
      map = new HashMap<String, Double>(); 
      FACTOR_MAP.put(from, map); 
     } 
     map.put(to, factor); 
    } 

    static { 
     registerFactor("cm", "mm", 10); 
     registerFactor("in", "cm", 2.54); 
     registerFactor("in", "pt", 72); 
     registerFactor("pc", "pt", 12); 
     registerFactor("px", "mm", 0.28); 
    } 

    private static class Step { 
     private String unit; 
     private double value; 

     Step(String unit, double value) { 
      this.unit = unit; 
      this.value = value; 
     } 
    } 
} 

下面的程序:

public class Main { 
    private static final String UNITS[] = {"cm", "mm", "in", "pt", "pc", "px"}; 

    public static void main(String[] args) { 
     for (String unit1: UNITS) { 
      for (String unit2: UNITS) { 
       System.out.println("1" + unit1 + " = " 
         + Converter.convert(unit1, unit2, 1) + unit2); 
      } 
     } 
    } 
} 

給出以下的結果:

1cm = 1.0cm 
1cm = 10.0mm 
1cm = 0.39370078740157477in 
1cm = 28.346456692913385pt 
1cm = 2.3622047244094486pc 
1cm = 35.71428571428571px 
1mm = 0.1cm 
1mm = 1.0mm 
1mm = 0.03937007874015748in 
1mm = 2.8346456692913384pt 
1mm = 0.23622047244094485pc 
1mm = 3.571428571428571px 
1in = 2.54cm 
1in = 25.4mm 
1in = 1.0in 
1in = 72.0pt 
1in = 6.0pc 
1in = 90.71428571428571px 
1pt = 0.035277777777777776cm 
1pt = 0.35277777777777775mm 
1pt = 0.013888888888888888in 
1pt = 1.0pt 
1pt = 0.08333333333333333pc 
1pt = 1.2599206349206347px 
1pc = 0.42333333333333334cm 
1pc = 4.233333333333333mm 
1pc = 0.16666666666666666in 
1pc = 12.0pt 
1pc = 1.0pc 
1pc = 15.119047619047619px 
1px = 0.028000000000000004cm 
1px = 0.28mm 
1px = 0.011023622047244094in 
1px = 0.7937007874015748pt 
1px = 0.06614173228346457pc 
1px = 1.0px 
+0

我喜歡這一款。但是,你不覺得現在對所有這些字符串定義有依賴嗎?是的,當然他們可以被外化,但是想法是讓設計保持開放,這樣你就不必修改現有的代碼來添加新的行爲。例如,如果我要添加一個新的「因子定義」,我想通過添加一個新類並將其作爲參數發送給我的轉換程序來完成。 – Jay 2010-06-08 15:59:44

+0

這只是一個例子。沒有什麼能夠阻止你使用別的東西而不是字符串(event plain Objects)。 – 2010-06-09 07:59:51