下面的例子主要來自《大話設計模式》:
小菜面試時,要求用任何一種面相對象的設計語言c#、java、python等寫一到計算器題目。小菜十分鐘不到就寫完了。程序如下:
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("請輸入第一個數字:");
String numberOne = sc.next();
System.out.println("請輸入計算符:");
//用於jdk1.7之前 獲取char
//char calcChar = sc.next().charAt(0);
// 用於jdk1.7及之後
String calcChar = sc.next();
System.out.println("請輸入第二個數字:");
String numberTwo = sc.next();
int result = 0;
try {
// jdk 1.7之前只能使用int 、short 、byte 、char。jdk 1.7及之後可以使用String。本示例採用jdk 1.8
switch (calcChar){
case "+":
result = Integer.parseInt(numberOne) + Integer.parseInt(numberTwo);
break;
case "-":
result = Integer.parseInt(numberOne) - Integer.parseInt(numberTwo);
break;
case "*":
result = Integer.parseInt(numberOne) * Integer.parseInt(numberTwo);
break;
case "/":
result = Integer.parseInt(numberOne) / Integer.parseInt(numberTwo);
break;
default:
throw new RuntimeException("計算符輸入錯誤");
}
}catch (Exception e){
e.printStackTrace();
System.out.println("分母不能爲0,或者數字輸入錯誤,或者計算符輸入錯誤");
System.exit(0);
}
System.out.println("運算結果爲:" + result);
}
}
小菜面試完之後便跟表哥大鳥說起了這件事,大鳥說:你感覺寫得怎麼樣,理解了面試題目的真正意思沒。小菜說了自己如何如何(小菜最後當然落榜了)。大鳥就說:人家要求用面嚮對象語言進行設計,面向對象的特性:封裝、繼承、多態,界面應該要和業務分開,以後無論是手機端、web端、pc端都能公用。你達到了沒。小菜想了想,就改成了如下的程序: (一)封裝
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("請輸入第一個數字:");
String numberOne = sc.next();
System.out.println("請輸入計算符:");
//用於jdk1.7之前 獲取char
//char calcChar = sc.next().charAt(0);
// 用於jdk1.7及之後
String calcChar = sc.next();
System.out.println("請輸入第二個數字:");
String numberTwo = sc.next();
int result = 0;
try {
result = Calculator.calc(Integer.parseInt(numberOne),calcChar,Integer.parseInt(numberTwo));
}catch (Exception e){
e.printStackTrace();
System.out.println("分母不能爲0,或者數字輸入錯誤,或者計算符輸入錯誤");
System.exit(0);
}
System.out.println("運算結果爲:" + result);
}
}
class Calculator {
public static int calc(int numberOne,String calcChar, int numberTwo)throws Exception{
int result = 0;
// jdk 1.7之前只能使用int 、short 、byte 、char。jdk 1.7及之後可以使用String。本示例採用jdk 1.8
switch (calcChar){
case "+":
result = numberOne + numberTwo;
break;
case "-":
result = numberOne - numberTwo;
break;
case "*":
result = numberOne * numberTwo;
break;
case "/":
result = numberOne / numberTwo;
break;
default:
throw new RuntimeException("計算符輸入錯誤");
}
return result;
}
}
大鳥看了之後說:”孺子可教也,實現了界面和業務的分離,用了封裝這個特性,面向對象還有兩個特性沒用“。小菜說:“我實在想不出這麼小的程序如何用繼承和多態”。
大鳥說:“慢慢來,你要學的東西多着呢,你好好想想”。
第二天,小菜說:“這麼小的計算器程序怎麼用到面向對象的三個特性啊!繼承和多態怎麼用得到我實在想不出來”。
大鳥說:“很有鑽研精神嘛,你昨天寫的程序能夠做到靈活的可修改和擴展呢?如何增加開根(sqrt)運算”
小菜說:“在Calculator類中,switch增加一個分支就行了啊”
大鳥說:“問題是你要加一個平方根運算,卻需要讓加減乘除運算都得參加編譯,如果不小心把加法改成了減法,這豈不是大大糟糕。比如公司讓你更改一個人員層級薪資的運算,還要給你各個管理層的運算代碼,你對自己的薪資不滿意,稍加修改,不是問題很大了。”
(二)繼承
class Calculator {
private int numberOne;
private int numberTwo;
public int getNumberOne() {
return numberOne;
}
public void setNumberOne(int numberOne) {
this.numberOne = numberOne;
}
public int getNumberTwo() {
return numberTwo;
}
public void setNumberTwo(int numberTwo) {
this.numberTwo = numberTwo;
}
public int getResult(){
int result = 0;
return result;
}
}
class AddCalculator extends Calculator{
@Override
public int getResult() {
return getNumberOne() + getNumberTwo();
}
}
class SubCalculator extends Calculator{
@Override
public int getResult() {
return getNumberOne() - getNumberTwo();
}
}
class MulCalculator extends Calculator{
@Override
public int getResult() {
return getNumberOne() * getNumberTwo();
}
}
class DivCalculator extends Calculator{
@Override
public int getResult(){
if(getNumberTwo() == 0)
throw new RuntimeException("除數不能爲0");
return getNumberOne() / getNumberTwo();
}
}
大鳥說:“寫得不錯嘛,大大超過了我的預想,你現在未解決的問題就是去實例化的問題,採用“簡單工廠模式”就可解決”。import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("請輸入第一個數字:");
String numberOne = sc.next();
System.out.println("請輸入計算符:");
//用於jdk1.7之前 獲取char
//char calcChar = sc.next().charAt(0);
// 用於jdk1.7及之後
String calcChar = sc.next();
System.out.println("請輸入第二個數字:");
String numberTwo = sc.next();
int result = 0;
try {
Calculator calculator = CalculatorFactory.createCalculator(calcChar);
calculator.setNumberOne(Integer.parseInt(numberOne));
calculator.setNumberTwo(Integer.parseInt(numberTwo));
result = calculator.getResult();
}catch (Exception e){
e.printStackTrace();
System.out.println("分母不能爲0,或者數字輸入錯誤,或者計算符輸入錯誤");
System.exit(0);
}
System.out.println("運算結果爲:" + result);
}
}
class Calculator {
private int numberOne;
private int numberTwo;
public int getNumberOne() {
return numberOne;
}
public void setNumberOne(int numberOne) {
this.numberOne = numberOne;
}
public int getNumberTwo() {
return numberTwo;
}
public void setNumberTwo(int numberTwo) {
this.numberTwo = numberTwo;
}
public int getResult(){
int result = 0;
return result;
}
}
class AddCalculator extends Calculator{
@Override
public int getResult() {
return getNumberOne() + getNumberTwo();
}
}
class SubCalculator extends Calculator{
@Override
public int getResult() {
return getNumberOne() - getNumberTwo();
}
}
class MulCalculator extends Calculator{
@Override
public int getResult() {
return getNumberOne() * getNumberTwo();
}
}
class DivCalculator extends Calculator{
@Override
public int getResult(){
if(getNumberTwo() == 0)
throw new RuntimeException("除數不能爲0");
return getNumberOne() / getNumberTwo();
}
}
class CalculatorFactory{
public static Calculator createCalculator(String calcChar){
Calculator calculator = null;
// jdk 1.7之前只能使用int 、short 、byte 、char。jdk 1.7及之後可以使用String。本示例採用jdk 1.8
switch (calcChar){
case "+":
calculator = new AddCalculator();
break;
case "-":
calculator = new SubCalculator();
break;
case "*":
calculator = new MulCalculator();
break;
case "/":
calculator = new DivCalculator();
break;
default:
throw new RuntimeException("計算符輸入錯誤");
}
return calculator;
}
}
自己的感悟,以後碰到switch想想用這個方法改寫。先做到“有劍勝無劍”,最後做到“無劍勝有劍”。