小菜成長記(一)--簡單工廠設計模式

       工作兩年多了,學了各種東西,android、html5、css、js、大數據、java後端,工作的坎坷,最後還是打算從事java後臺,博而不精,面試有點小困難,雖然每次面試過後越來越好,但是達不到自己最想要去的公司和工作。面試了某家大型公司,最後面試官說,你工作兩年了還是個初級工程師,不管技術如何更新,基礎纔是最重要,事情總要人去做,雖然最終落榜。沉靜下來,兩個月初看完了《java編程思想》、《深入理解java虛擬機》,心裏大概有個底,知道什麼技術解決什麼問題,過段時間再看一次,知道完全理解爲止,期間也看了炒股方面的書:《聰明的投資者》(美)本傑明·格雷厄姆、《在股市大崩潰前拋出的人:巴魯克自傳》、《巴菲特基金投資6招》劉建位 徐曉傑、《長盈之道》約翰.博格。現在開始學習設計模式《大話設計模式》,感謝程傑老師寫的這本書。
下面的例子主要來自《大話設計模式》:
小菜面試時,要求用任何一種面相對象的設計語言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想想用這個方法改寫。先做到“有劍勝無劍”,最後做到“無劍勝有劍”。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章