Java 入門指南 V2.00 - 單元 13 - Encrypt 類別




利用 Java 寫程式 (program) ,著重在設計類別 (class) ,然後規劃物件 (object) 的使用、物件與物件間的互動,同時要注意,一個物件專心做好一件事情就好,類別的設計不應該太過複雜



我們打算發展的一個替英文句子編密碼的軟體,主要功能是做小寫字母的替換,例如 "There is no spoon." 可能變成以下任一個


Tfqdq ki jo itooj.
Tcnan hf gl fqllg.
Tczmz dn ij nkjji.
Tgfsf pb ir barri.
Tdcpc my fo yxoof.


首先,我們要發展 Encrypt 類別,主要功能是建立一個英文小寫字母的對換表格,藉由這個表格,我們可以將英文句子中的小寫英文字母進行對換,最終開發圖形使用者介面 (graphical user interface) 的 Encryptor 專案 (project) 。


GUI 的外觀如下圖



GUI 的部份採用 JavaFX 設計,這需要用到 NetBeans 及 JavaFX Scene Builder 兩個隨 JDK 下載的軟體,其中 NetBeans 為官方提供的整合開發環境 (integrated development environment) ,而 JavaFX Scene Builder 則可直接在軟體視窗中拉出 JavaFX 的 GUI 外觀。

有兩個可供輸入的文字欄位 (text field) ,其中一個我們作為輸出的顯示訊息之用,另有三個標籤 (label) ,顯示文字的提示訊息,七個按鈕 (button) ,提供「新建」、「開啟」、「儲存」 Encrypt 物件,與「編碼」、「解碼」所輸入的英文句子,「清除」所有輸入欄位,以及「拷貝」輸出結果等的功能。


現在我們先來看看所有功能的核心,也就是 Encrypt 類別,我們的目的是,建立一個小寫英文字母的轉換表格,然後編碼、解碼都可直接依據這個表格。我們打算用下面的數學公式建立表格


y = a * x + b
m = y % n
r = m + diff


這裡的概念是利用字元的 Unicode 編碼順序,假設 x 為字元的原始編碼, Unicode 編碼中 'a'97 ,然後將 x 乘上變數 (variable) a , 再加上變數 b ,假設兩者均是 09 的隨機整數,這樣便得到 y 的值。


然後將 y 除以 n 取得餘數 mn 為所要轉換的字元數量,英文小寫字母共有 26 個,所以這裡 n 等於 26 ,因此 m 等於 025 之間的整數值。最後將 m 加上 diffdiff 也就是編碼系統的差值,由於 Unicode 中 'a'97 ,所以這裡 diff 要以 97 代入。


因此,餘數 0 的字元會替換成 'a' ,餘數 1 的字元會被替換成 'b' ,餘數 2 的字元會被替換成 'c' ,餘下 23 個字元類推。這樣的計算需要進行 n 次,也就是 26 次,我們最後得到一組餘數與相對應字元的表格,這就是我們需要的表格了。


重複 n 次,我們需要一個迴圈 (loop) ,由於重複次數確定,因此 for 迴圈 (for loop) 很適合,那我們要用什麼東西來儲存這個表格呢? API 中有許多的資料結構 (data structure) ,可以依資料特性有效率的處理資料,簡單一點,我們利用陣列 (array) 就可以了。


陣列是一種儲存可以多個相同型態資料的資料結構,索引值 (index) 從 0 開始,這也完全符合我們計算餘數從 0 開始的需求。


我們先寫一個 Encrypt 的試做版本 Encrypt01 來看看吧


001public class Encrypt01 {
002   // 密碼表字元陣列
003   private char[] code = new char[26];
004
005   // 建構子
006   public Encrypt01() {
007      setCode();
008   }
009
010   // setter
011   public void setCode() {
012      char c = 'a';
013      for (int i = 0; i < 26; i++) {
014         code[i] = c++;
015      }
016   }
017
018   // getter
019   public char[] getCode() {
020      return code;
021   }
022
023   // 編碼的方法
024   public String toEncode(String s) {
025      return s;
026   }
027
028   // 解碼的方法
029   public String toDecode(String s) {
030      return s;
031   }
032
033   // 測試的 main()
034   public static void main(String[] args) { 
035      Encrypt01 e = new Encrypt01();
036      System.out.println(e.code);
037      String s = "There is no spoon";
038      System.out.println(s);
039      String s1 = e.toEncode(s);
040      System.out.println(s1);
041      String s2 = e.toDecode(s1);
042      System.out.println(s2);
043   }
044}
045 
046/* 檔名: Encrypt01.java
047   作者: Kaiching Chang
048   時間: September, 2014 */

首先宣告 private 的密碼表字元陣列屬性 code


002// 密碼表字元陣列
003private char[] code = new char[26];

這裡用 new 建立陣列物件,目的是宣告完直接分配記憶體空間。

下面除了建構子 (constructor) 及 setCode()getCode() 外,還有需要一個 String 參數 (parameter) 也回傳 StringtoEncode()toDecode() ,這兩個都暫時回傳參數,待稍候的單元再實作。


建構子簡單的呼叫 setCode() ,目前 setCode() 的版本為建立二十六個英文小寫字母表


010// setter
011public void setCode() {
012   char c = 'a';
013   for (int i = 0; i < 26; i++) {
014      code[i] = c++;
015   }
016}

這也是個暫時的版本,讓我們測試的 main() 可以正常運作


033// 測試的 main()
034public static void main(String[] args) { 
035   Encrypt01 e = new Encrypt01();
036   System.out.println(e.code);
037   String s = "There is no spoon";
038   System.out.println(s);
039   String s1 = e.toEncode(s);
040   System.out.println(s1);
041   String s2 = e.toDecode(s1);
042   System.out.println(s2);
043}

編譯執行,結果如下



接下來我們要在 setCode() 中實作製作密碼表的公式囉!


中英文術語對照


程式program
類別class
物件object
圖形使用者介面graphical user interface
專案project
整合開發環境integrated development environment
文字欄位text field
標籤label
按鈕button
變數variable
迴圈loop
for 迴圈for loop
資料結構data structure
陣列array
索引值index
建構子constructor
參數parameter

重點整理


  1. Java 寫程式著重在設計類別,規劃物件的使用及物件與物件之間的互動。
  2. Encrypt 類別利用數學公式進行英文小寫字母的替換, Encrypt01 則是第一個試做版本。
  3. 陣列是一種簡單的資列結構,可以儲存有限個相同資料型態的資料。

問題與討論


  1. 類別應該怎麼設計才不會太過複雜?
  2. 除了數學公式外,有其他的方式可以建立對換表格嗎?
  3. 為什麼要用到強制型態轉換?如果不做強制型態轉換會發生什麼結果?

the end

沒有留言: