emmm......之是以寫這個系列,是因為想去進階,感覺寫自己代碼不夠精簡,亢沉臃腫;想寫好寫優雅寫優秀,卻不知道是不是優秀,模棱兩可的感覺;想去入手源碼,卻不知道從拿下手,又或者說看不懂,為什麼這麼寫。
是以想入手設計模式系列,當然這些了解或者示例代碼是建立在《大話設計模式》——程傑著的基礎之上的。感覺這本書還是值得推薦的_
僅屬個人了解,如果有誤,歡迎各位指正^_^
在未接觸到設計模式之前,你的代碼或許是這樣的:
/**(模拟一個電腦的功能)*/
public class General {
public static void main(String[] args) {
//普通代碼
try {
Scanner sc = new Scanner(System.in);
System.out.println("輸入數字A:");double strNumberA = sc.nextInt();
System.out.println("輸入數字B:");double strNumberB = sc.nextInt();
System.out.println("輸入運算符:");String opera = sc.next();
String result = "";
result = getResult(strNumberA, opera, strNumberB, result);
if(Optional.ofNullable(result).isPresent()){//判斷是否傳回空,false為空
System.out.println("您輸出的結果為:"+result);
}else{
System.out.println("請輸入正确的運算符");
}
}catch (Exception ex){
System.out.println("您的輸入有誤"+ex.getMessage());
}
}
public static String getResult(double strNumberA, String opera, double strNumberB, String result) {
switch (opera){
case "+":
result = String.valueOf(strNumberA + strNumberB);
break;
case "-":
result = String.valueOf(strNumberA - strNumberB);
break;
case "*":
result = String.valueOf(strNumberA * strNumberB);
break;
case "/":
result = String.valueOf(strNumberA / strNumberB);
break;
default:
result = null;
break;
}
return result;
}
}
其實,乍一看這段代碼也沒什麼問題,并且也運用到了面向對象三大特征——封裝,而且也捕獲了異常,按道理也挺完善了,但是,如果讓你同時用到面向對象的三大特征呢?又或者說這個代碼能否做到靈活的修改和擴充呢?
引入簡單工廠模式(工廠模式細分為:簡單工廠,工廠模式,抽象工廠)劃重點
從以上代碼你也可以看出,耦合性很高,每次拓展一個功能(比如我在增加個幂運算),都要在switch加一個分支,進而導緻加減乘除運算都得重新編譯,而且是在原寫好的類上修改,極不利于維護和拓展。
而此時,如果你用到了簡單工廠模式,就可以巧妙的避開這些。
優點:
- 解耦:調用方不用負責對象的建立,隻需要使用,明确各自的職責;
- 維護友善:後期如果建立對象時需要修改代碼,也隻需要去工廠方法中修改,易拓展;
運用簡單工廠模式改造的思路如下:
- 定義中繼資料類(抽象類,不需要執行個體,需要子類重寫),運用到了封裝;
- 具體實體類(加減乘除類)運用到了繼承;
- 簡單工廠類(選擇傳來的是加減乘除哪一個算法)運用到了多态。
具體代碼實作:
- 定義中繼資料類:
public abstract class MetaData {
private double numberA;
private double numberB;
//具體方法,需要子類去重寫
public abstract String getResult(double numberA,double numberB);
get/set方法...
}
- 定義具體實作類:
//加法 public class MetaDataAdd extends MetaData{ public String getResult(double numberA,double numberB){ String result = String.valueOf(numberA + numberB); return result; } }
//減法 public class MetaDataReduce extends MetaData{ public String getResult(double numberA,double numberB){ String result = String.valueOf(numberA - numberB); return result; } }
//乘法 public class MetaDataMul extends MetaData{ public String getResult(double numberA,double numberB){ String result = String.valueOf(numberA * numberB); return result; } }
//除法 public class MetaDataDivision extends MetaData{ public String getResult(double numberA,double numberB){ String result = String.valueOf(numberA / numberB); return result; } }
- 簡單工廠類
public class MetaDataFactory { public static MetaData getAlgorithm(String operator){ MetaData metaData = null; switch (operator){ case "+": metaData = new MetaDataAdd(); //多态的實作 break; case "-": metaData = new MetaDataReduce();//多态的實作 break; case "*": metaData = new MetaDataMul();//多态的實作 break; case "/": metaData = new MetaDataDivision();//多态的實作 break; default: metaData = null; break; } return metaData; } }
總結
這樣下來,如果你增加一個幂運算,直接在工廠類裡面添加一個switch分支,在建立一個幂算法。而這樣對于日後的維護和擴充會更加友好。