撰寫程式常有些看似不合理但又非得完成的需求,舉個例子來說,現在老闆叫你開發一個猜數字遊戲,會隨機產生0到9的數字,使用者輸入的數字與隨機產生的數字相比,如果相同就顯示「猜中了」,如果不同就繼續讓使用者輸入數字,直到猜中為止。
這程式有什麼難的?相信現在的你也可以實作出來:
package cc.openhome;
import java.util.Scanner;
public class Guess {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int number = (int) (Math.random() * 10);
int guess;
do {
System.out.print("輸入數字:");
guess = scanner.nextInt();
} while(guess != number);
System.out.println("猜中了");
}
}
圓滿達成任務是吧!當你將程式交給老闆後,老闆皺著眉頭說:「我有說要在文字模式下執行這個遊戲嗎?」你就問了:「請問會在哪個環境下執行呢?」老闆說:「還沒決定,也許會用視窗程式,不過改成網頁也不錯,唔...下個星期開會討論一下。」你問:「那可以下星期討論完我再來寫嗎?」老闆說:「不行!」你(內心OS):「當我是哆啦A夢喔!我又沒有時光機....」
這個例子可笑嗎?在團隊合作、多個部門開發程式時,有許多時候,你不能只是等另一個部門將程式實作出來,也許另一部門要三個月後才能完成程式實作,難道你們這個部門要空轉三個月?有些需求無法決定,卻要撰寫出程式的例子太多了....
有些不合理的需求,本身確實不合理,但有些看似不合理的需求,其實可以設過設計(Design)來解決,以上面的例子來說,取得使用者輸入、顯示結果的環境未定,但你負責的這部份還是可以先實作。例如:
package cc.openhome;
public abstract class GuessGame {
public void go() {
int number = (int) (Math.random() * 10);
int guess;
do {
print("輸入數字:");
guess = nextInt();
} while(guess != number);
println("猜中了");
}
public void println(String text) {
print(text + "\n");
}
public abstract void print(String text);
public abstract int nextInt();
}
這個類別的定義不完整,print()
與nextInt()
都是抽象方法,因為老闆還沒決定在哪個環境執行猜數字遊戲,所以如何顯示輸出、取得使用者輸入就不能實作,可以先實作的是猜數字的流程,雖然是抽象方法,但在go()
方法中,還是可以呼叫。
等到下星期開會決定,終於還是在文字模式下執行猜數字遊戲,你就再撰寫ConsoleGame
類別,繼承抽象類別GuessGame
,實作當中的抽象方法即可:
package cc.openhome;
import java.util.Scanner;
public class ConsoleGame extends GuessGame {
private Scanner scanner = new Scanner(System.in);
@Override
public void print(String text) {
System.out.print(text);
}
@Override
public int nextInt() {
return scanner.nextInt();
}
}
實際上你只要建構出ConsoleGame
實例,執行go()
方法過程中呼叫到print()
、nextInt()
方法時,都是執行ConsoelGame
中定義的流程,完整的猜數字遊戲就實作出來了。例如:
package cc.openhome;
public class Guess {
public static void main(String[] args) {
GuessGame game = new ConsoleGame();
game.go();
}
}
一個執行的結果如下:
輸入數字:4
輸入數字:3
猜中了