[java] 匯率換算器實現(1)
[java] 匯率換算器實現(1)
Table of Contents
1 問題描述
實現不同貨幣之間的匯率換算.
名詞: 貨幣, 匯率
動詞: 換算
2 類設計
class list:
- Money
- double amount: 貨幣的數量
- String unit: 貨幣的單位
- Rate
- private Hashtable rateTable: 用來存儲不同貨幣之間的匯率
3 初步實現
3.1 建立項目目錄結構
. ├── build.xml ├── lib │ ├── hamcrest-core.jar │ └── junit.jar ├── README.txt ├── run └── src └── com └── cnblogs └── grassandmoon
其中, build.xml為ant執行所需的配置文件. run為shell文件, 用於運行編譯后的java程序.
build.xml文件內容如下:
1 <?xml version="1.0"?>
2
3 <!-- build.xml - a simple Ant buildfile -->
4 <project name="javacookbook" default="all" basedir=".">
5
6 <!-- The directory containing source code -->
7 <property name="src.dir" value="src"/>
8 <property name="lib.dir" value="lib"/>
9
10 <!-- Temporary build directories -->
11 <property name="build.dir" value="build"/>
12 <property name="build.classes" value="${build.dir}/classes"/>
13
14 <property name="java.lib" value="${java.home}/jre/lib/rt.jar"/>
15
16 <!-- Target to create the build directories prior to the -->
17 <!-- compile target. -->
18 <target name="prepare">
19 <mkdir dir="${build.dir}"/>
20 <mkdir dir="${build.classes}"/>
21 </target>
22
23 <target name="all" depends="project"/>
24
25 <target name="project" depends="prepare">
26 <javac srcdir="${src.dir}"
27 destdir="${build.classes}"
28 classpath="${java.lib}:${lib.dir}/junit.jar:${build.classses}"
29 debug="on"
30 includeantruntime="on"/>
31 </target>
32
33 <target name="clean" description="Remove all generated files.">
34 <delete dir="${build.dir}"/>
35 </target>
36 </project>
3.2 建立測試文件
/** TestRate.java * 用於貨幣匯率轉換工具的測試 */ package com.cnblogs.grassandmoon; import static org.junit.Assert.assertEquals; import org.junit.Test; public class TestRate { @Test public void testGetRate() { Money m = new Money(150, "USD"); Rate.setRate("USD", "CNY", 6.25); Money mCNY = Rate.exchangeRate(m, "CNY"); assertEqual(new Money(150*6.25, "CNY"), mCNY); } }
3.3 對應的實現文件, Money
package com.cnblogs.grassandmoon; import java.util.*; class Rate { // 利用hashtable對不同貨幣之間的利率進行存儲 // key: $from+$to, value: $rate private static Hashtable rateTable = new Hashtable(); // 設置不同貨幣之間的利率 // 1 $from * $rate = 1 $to public static void setRate(String from, String to, double rate) { rateTable.put(from+to, new Double(rate)); } private static double getRate(String key) { Double db = (Double) rateTable.get(key); return db.doubleValue(); } // 將一定量的貨幣$m, 轉變成單位為$to的貨幣量 // return: 相應的貨幣值 public static Money exchangeRate(Money m, String to) { if (m.unit == to) return new Money(m); String key = m.unit + to; double rate = getRate(key); return new Money(m.amount*rate, to); } } public class Money { double amount; String unit; public Money(double amount, String unit) { setMoney(amount, unit); } public Money(Money m) { setMoney(m.amount, m.unit); } public void setMoney(double amount, String unit) { this.amount = amount; this.unit = unit; } public boolean equals(Object obj) { Money other = (Money) obj; return amount == other.amount && unit.equals(other.unit); } }
3.4 增加輸入輸出: 一般化
有哪些內容需要進行輸入輸出呢?
輸入
- 歡迎信息
歡迎使用匯率轉換器 版本: 1.0 作者: 鍾謝偉
- 幫助信息
1. 輸入不同貨幣以及對應的匯率信息, 第一個為需要轉換的貨幣單位 第二個為轉換到的目標貨幣單位 第三個為相應的匯率 不同項目之間用空格隔開 如: USD CNY 6.25 表示: 1 USD * 6.25 = 1 CNY 2. 輸入待轉換量, 用空格隔開 如: 150 USD 3. 幫助 4. 退出 請進行選擇 (1, 2, 3 or 4)
- 不同貨幣單位以及相應的匯率
- 需要進行轉換的貨幣量
輸出
- 轉換后的結果
如: 150 USD = 937.50 CNY
3.5 對應的實現, MoneyDemo
見初步實現代碼.
3.6 小結
目前已經完成的功能:
- 人為的輸入匯率
- 根據輸入的匯率進行轉換
需要進一步增加的功能:
- 當輸入錯誤時, 如何進行處理?
- 當需要轉換的貨幣單位, 沒有在匯率表中時, 如何進行處理?
- 如何克服每次手動增加匯率的麻煩之處?
下面將根據上述的問題進行進一步的改進.
4 進一步的改進
4.1 輸入格式統一以及錯誤處理
為了減少代碼的重復量, 需要對匯率輸入, 以及轉換輸入的格式進行統一, 如下:
- 匯率輸入: 匯率 from幣種 to幣種, 如 6.25 USD CNY
- 轉換輸入: from幣種貨幣量 from幣種 to幣種, 如 100 USD CNY
然后對輸入的錯誤情況進行了處理:
- 格式錯誤
- 匯率轉換過程中遇到沒有相應的匯率信息的情況處理
此時的結果如下: #中間代碼
1 // MoneyDemo.java
2 package com.cnblogs.grassandmoon; 3
4 import java.io.*; 5
6 class Helper { 7 public static void printVersion() { 8 System.out.println("歡迎使用匯率轉換器"); 9 System.out.println("版本: 1.0"); 10 System.out.println(); 11 System.out.println("作者: 鍾謝偉"); 12 System.out.println("email: grass-of-sky@163.com"); 13 System.out.println(); 14 } 15
16 public static void printHelp() { 17 System.out.println("1. 輸入不同貨幣以及對應的匯率信息,"); 18 System.out.println(" 第一個為相應的匯率"); 19 System.out.println(" 第二個為需要轉換的貨幣單位"); 20 System.out.println(" 第三個為轉換到的目標貨幣單位"); 21 System.out.println(" 不同項目之間用空格隔開"); 22 System.out.println(" " + getRateUsage()); 23 System.out.println(" 表示: 1 USD * 6.25 = 1 CNY"); 24 System.out.println(); 25 System.out.println("2. 輸入待轉換量, 用空格隔開"); 26 System.out.println(" " + getExchangeUsage()); 27 System.out.println(); 28 System.out.println("3. 幫助"); 29 System.out.println(); 30 System.out.println("4. 退出"); 31 System.out.println(); 32 printUsage(); 33 System.out.println(); 34 } 35
36 public static void printUsage() { 37 System.out.println("請選擇 (1, 2, 3 或者 4)"); 38 } 39
40 public static String getRateUsage() { 41 return "如: 6.25 USD CNY"; 42 } 43
44 public static String getExchangeUsage() { 45 return "如: 100 USD CNY"; 46 } 47 } 48
49 class ReadLineTokens { 50 public double value; 51 public String from; 52 public String to; 53
54 ReadLineTokens(double v, String f, String t) { 55 value = v; 56 from = f; 57 to = t; 58 } 59 } 60
61 public class MoneyDemo { 62 // 對匯率輸入, 以及轉換輸入進行處理, 提取不同的成份
63 static ReadLineTokens processReadLine(BufferedReader br) 64 throws IOException { 65 String inputLine = br.readLine(); 66 String tokens[] = inputLine.split(" "); 67 if (tokens.length == 1 && tokens[0].equals("q")) { 68 return null; 69 } 70
71 return new ReadLineTokens(new Double(tokens[0]), 72 tokens[1], 73 tokens[2]); 74 } 75
76 public static void main(String[] args) 77 throws IOException { 78 String cmdLine = null; 79 String inputMsg = null; 80 Money m = new Money(); 81 Money exchanged = new Money(); 82 ReadLineTokens tokens; 83 boolean inputError = false; 84 BufferedReader br = new
85 BufferedReader(new InputStreamReader(System.in)); 86 Helper.printVersion(); 87 Helper.printHelp(); 88
89 while (true) { 90 cmdLine = br.readLine(); 91 if (cmdLine.equals("1")) { 92 do { 93 try { 94 System.out.print("輸入匯率關系 " +
95 Helper.getRateUsage() +
96 " (退出當前選項 \"q\"): "); 97
98 // input "q" to quick this step
99 tokens = processReadLine(br); 100 if (tokens == null) { 101 break; 102 } 103
104 Rate.setRate(tokens.from, tokens.to, tokens.value); 105 System.out.println(); 106 inputError = false; 107 } catch (Exception e) { 108 System.out.println("\n\t請按照正確的格式進行輸入\n"); 109 inputError = true; 110 } 111 } while (inputError); 112 } else if (cmdLine.equals("2")) { 113 do { 114 try { 115 System.out.print("輸入待轉換量 " +
116 Helper.getExchangeUsage() +
117 " (退出當前選項 \"q\"): "); 118
119 // input "q" to quit this step
120 tokens = processReadLine(br); 121 if (tokens == null) { 122 break; 123 } 124
125 m.setMoney(tokens.value, tokens.from); 126 exchanged = Rate.exchangeRate(m, tokens.to); 127 System.out.println(m + " = " + exchanged); 128 System.out.println(); 129 inputError = false; 130 } catch (IllegalArgumentException e) { 131 System.out.println("\n\t匯率轉換表中沒有相應的轉換項\n"); 132 inputError = true; 133 } catch (Exception e) { 134 System.out.println("\n\t請按照正確的格式進行輸入\n"); 135 inputError = true; 136 } 137 } while (inputError); 138 } else if (cmdLine.equals("3")) { 139 Helper.printHelp(); 140 } else if (cmdLine.equals("4")) { 141 break; 142 } else { 143 Helper.printUsage(); 144 } 145 } 146 } 147 } 148
149 // Money.java
150 package com.cnblogs.grassandmoon; 151
152 import java.util.*; 153
154 class Rate { 155 // 利用hashtable對不同貨幣之間的利率進行存儲 156 // key: $from+$to, value: $rate
157 private static Hashtable rateTable = new Hashtable(); 158
159 // 設置不同貨幣之間的利率 160 // 1 $from * $rate = 1 $to
161 public static void setRate(String from, String to, double rate) { 162 rateTable.put(from+to, new Double(rate)); 163 } 164
165 // 將一定量的貨幣$m, 轉變成單位為$to的貨幣量 166 // return: 相應的貨幣值
167 public static Money exchangeRate(Money m, String to) { 168 if (m.unit.equals(to)) return new Money(m); 169 String key = m.unit + to; 170 Double rate = (Double) rateTable.get(key); 171
172 if (rate == null) { 173 throw new IllegalArgumentException(); 174 } 175
176 return new Money(m.amount*rate.doubleValue(), to); 177 } 178 } 179
180 public class Money { 181 double amount; 182 String unit; 183
184 public String toString() { 185 return amount + " " + unit; 186 } 187
188 public Money() { 189 setMoney(0.0, null); 190 } 191
192 public Money(double amount, String unit) { 193 setMoney(amount, unit); 194 } 195
196 public Money(Money m) { 197 setMoney(m.amount, m.unit); 198 } 199
200 public void setMoney(double amount, String unit) { 201 this.amount = amount; 202 this.unit = unit; 203 } 204
205 public boolean equals(Object obj) { 206 Money other = (Money) obj; 207 return amount == other.amount 208 && unit.equals(other.unit); 209 } 210 }
4.2 調用最新的匯率信息
將在下次繼續.