大話設計模式--(1)簡單工廠模式
阿新 • • 發佈:2018-12-13
實現一個計算器控制檯程式,要求輸入兩個數和運算子號,得到結果。
我的第一反應是和書裡的是一樣的就是向下面這樣寫
/* * 要求輸入兩個數和運算子號,得到結果 * */ public class Test { public static void main(String []args) throws IOException { System.out.print("輸入第一個數:"); Scanner scan = new Scanner(System.in); String read1 = scan.nextLine(); System.out.print("輸入運算方式:"); Scanner scan2 = new Scanner(System.in); String read2 = scan2.nextLine(); System.out.print("輸入第二個數:"); Scanner scan3 = new Scanner(System.in); String read3 = scan3.nextLine(); int result=0; if(read2.equals("+")){ result=Integer.parseInt(read1)+Integer.parseInt(read3); }else if (read2.equals("-")){ result=Integer.parseInt(read1)-Integer.parseInt(read3); }else if (read2.equals("*")){ result=Integer.parseInt(read1)*Integer.parseInt(read3); }else if (read2.equals("/")){ result=Integer.parseInt(read1)/Integer.parseInt(read3); } System.out.print("計算結果為:"+result); } }
繼續看,初學者的毛病,命名不規範,判斷分支(假如說是除法,那麼前面三次就相當於做了無用功),然後出發的除數有可能為0會拋異常
public class Test { public static void main(String []args) { try { System.out.print("輸入第一個數:"); Scanner scan = new Scanner(System.in); String read1 = scan.nextLine(); System.out.print("輸入運算方式:"); Scanner scan2 = new Scanner(System.in); String read2 = scan2.nextLine(); System.out.print("輸入第二個數:"); Scanner scan3 = new Scanner(System.in); String read3 = scan3.nextLine(); int result=0; switch (read2){ case "+": result=Integer.parseInt(read1)+Integer.parseInt(read3); break; case "-": result=Integer.parseInt(read1)-Integer.parseInt(read3); break; case "*": result=Integer.parseInt(read1)*Integer.parseInt(read3); break; case "/": if (Integer.parseInt(read3)!=0){ result=Integer.parseInt(read1)+Integer.parseInt(read3); }else { System.out.print("被除數不可為0"); } break; } System.out.print("計算結果為:"+result); }catch (Exception ex){ System.out.print("輸入的引數有誤,請重新輸入"); } } }
至少就目前程式碼來看,實現了基本的計算器功能,但是是否符合出題人的意思,意思是是否符合“面向物件”。書裡原話:所有的初學者就是碰到問題就直覺的用計算能夠理解的邏輯來描述和表達待解決的問題以及具體的求解過程,這其實是用計算機的方式去思考,比如計算器這個程式,現要求輸入兩個數和運算子號,然後再根據運算子號判斷選擇如何運算,得到結果,這個本身沒錯,但這樣的思維卻使得我們的程式只為了滿足當前的需求,程式不容易維護,不容器擴充套件,更不易服用,從而達不到高質量程式碼的要求。
程式碼中的重複程式碼多到一定程度,維護的時候,可能就是一場災難,越大的系統,這種方式帶來的問題越嚴重,程式設計有一原則,就是用盡可能的方法去避免重複。檢視那些是和控制檯無關的,那些只是和計算有關的,準確的說讓業務邏輯與介面邏輯分開,讓他們之間的耦合度下降,只有分離開,才可以達到容易維護和擴充套件
/* * 要求輸入兩個數和運算子號,得到結果 * */ public class Test { /* *運算方法 * */ public static int getResult(String one, String two, String middle){ int result=0; switch (middle){ case "+": result=Integer.parseInt(one)+Integer.parseInt(two); break; case "-": result=Integer.parseInt(one)-Integer.parseInt(two); break; case "*": result=Integer.parseInt(one)*Integer.parseInt(two); break; case "/": if (Integer.parseInt(two)!=0){ result=Integer.parseInt(one)+Integer.parseInt(two); }else { System.out.print("被除數不可為0"); } break; } return result; } public static void main(String []args) { try { System.out.print("輸入第一個數:"); Scanner scan = new Scanner(System.in); String read1 = scan.nextLine(); System.out.print("輸入運算方式:"); Scanner scan2 = new Scanner(System.in); String read2 = scan2.nextLine(); System.out.print("輸入第二個數:"); Scanner scan3 = new Scanner(System.in); String read3 = scan3.nextLine(); int result=0; result=getResult(read1,read3,read2); System.out.print("計算結果為:"+result); }catch (Exception ex){ System.out.print("輸入的引數有誤,請重新輸入"); } } }
如果新新增一個運算規則,需要修改swich裡面程式碼,很有可能會動到原來執行穩定的程式碼,這樣風險太大。要運用繼承,多型,
首先寫了一個演算法類,裡面只有2個數,然後再用加減乘除類繼承並重寫演算法類裡面的一個方法
public class Operation { private double _numberA=0; private double _numberB=0; public double get_numberB() { return _numberB; } public void set_numberB(double _numberB) { this._numberB = _numberB; } public double get_numberA() { return _numberA; } public void set_numberA(double _numberA) { this._numberA = _numberA; } public double GetResult(){ double result=0; return result; } } /* * 加法 * */ class add extends Operation{ @Override public double GetResult() { double result=0; result=get_numberA()+get_numberB(); return result; } } /* * 減法 * */ class Subtraction extends Operation{ @Override public double GetResult() { double result=0; result=get_numberA()-get_numberB(); return result; } } /* * 乘法 * */ class multiplication extends Operation{ @Override public double GetResult() { double result=0; result=get_numberA()*get_numberB(); return result; } } /* * 除法 * */ class division extends Operation{ @Override public double GetResult() { double result=0; if (get_numberB()!=0){ result=get_numberA()/get_numberB(); }else{ System.out.print("被除數不可為0"); } return result; } }
然後再寫一個簡單工廠類就可以了,只需要輸入運算子號,工廠就例項化出合適的物件,通過多型返回父類的方式實現了計算器的結果
public class OperationFactory { public static Operation createOperate(String operate){ Operation operation=null; switch (operate){ case "+": operation=new add(); break; case "-": operation=new Subtraction(); break; case "*": operation= new multiplication(); break; case "/": operation=new division(); break; } return operation; } }
測試:
public class Test { public static void main(String []args) { Operation operate = OperationFactory.createOperate("+"); operate.set_numberA(5); operate.set_numberB(2); System.out.println(operate.GetResult()); } }