大話設計模式筆記(一)の簡單工廠模式

概要

  • 一個好的程序猿/媛敲出來的代碼應該是可維護、可複用、可擴展的,也就是具備較好的靈活性。
  • 爲了達到以上目的,在還沒敲代碼以前,須要事先考慮經過何種方式可以使本身的程序的耦合度下降,最基本的即是面向對象的封裝、繼承、多態
  • 但這每每是不夠的,須要根據實際狀況選擇合適的設計模式使得程序變得更加靈活,容易修改,而且易於複用
  • 複用並非複製的意思。在實際開發當中,有時候會遇到一些相似的功能,有一部分已是在別的 Service 中實現了(整個方法的功能是不同的),但可能出於項目趕進度的時候,也可能作這個功能的員工水平不足,因而乎直接將此處代碼一頓操做 ctrl + C / V 一切搞定。但對往後維護的人來講是一場災難,萬一又是本身,往後少不了「早知如此,何須當初」的感嘆了。養成好的編碼習慣很重要。
  • 話說得好聽誰都會,正是由於人都有成長的過程,因此對業務的理解轉化爲程序,以及編寫代碼的優美程度也是一步一個腳印走出來的。是否可以作到真正的鬆耦合,又或者「鬆」的過分致使程序過於臃腫,都跟我的的層次有關。付出不必定有收穫,但不付出,確定沒有收穫。

拋磚引玉

案例

實現一個簡單計算器代碼(加減乘除)設計模式

普通實現方式

/**
 * 運算類
 * Created by callmeDevil on 2019/5/26.
 */
public class Operation {

    /**
     * 獲取運算結果
     * @param numA 數值A
     * @param numB 數值B
     * @param operate 運算符
     * @return
     */
    public static double getResult(double numA, double numB, String operate) {
        double result = 0L;
        switch (operate) {
            case "+":
                result = numA + numB;
                break;
            case "-":
                result = numA - numB;
                break;
            case "*":
                result = numA * numB;
                break;
            case "/":
                result = numA / numB;
                break;
            default:
                break;
        }
        return result;
    }

}
/**
 * 測試類
 * Created by callmeDevil on 2019/5/26.
 */
public class Test {

    public static void main(String[] args) {
        Operation operation = new Operation();
        double numA = 10;
        double numB = 2;
        System.out.println("加法:" + operation.getResult(numA, numB, "+"));
        System.out.println("減法:" + operation.getResult(numA, numB, "-"));
        System.out.println("乘法:" + operation.getResult(numA, numB, "*"));
        System.out.println("除法:" + operation.getResult(numA, numB, "/"));
    }

}

可是這樣就有個問題,若是這個計算器還須要實現開根號運算呢?難道就直接在Operation類添加一個switch分支就好了嗎?不是的,這樣會讓原來良好運行的代碼產生變化,風險太大,所以須要將各類運算的邏輯分離開來,此處引入簡單工廠模式ide

簡單工廠模式實現

定義

又稱爲靜態工廠模式,根據工廠類傳入的參數動態決定建立某種類(這些類都繼承自同一父類或實現同一接口)的實例。測試

UML圖

結合代碼有註釋

/**
 * 運算基礎類
 * Created by callmeDevil on 2019/5/26.
 */
public class BaseOperation {

    private double numA;
    private double numB;

    // 此處省略get、set方法

    /**
     * 獲取結果
     * @return
     */
    public double getResult() {
        double result = 0L;
        return result;
    }

}
/**
 * 加法運算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationAdd extends BaseOperation {

    @Override
    public double getResult() {
        return getNumA() + getNumB();
    }

}
/**
 * 減法運算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationSub extends BaseOperation {

    @Override
    public double getResult() {
        return getNumA() - getNumB();
    }

}
/**
 * 乘法運算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationMul extends BaseOperation {

    @Override
    public double getResult() {
        return getNumA() * getNumB();
    }

}
/**
 * 除法運算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationDiv extends BaseOperation {

    @Override
    public double getResult() {
        if (getNumB() == 0){
            throw new RuntimeException("除數不能爲0!");
        }
        return getNumA() / getNumB();
    }

}
/**
 * 測試類
 * Created by callmeDevil on 2019/5/26.
 */
public class Test {

    public static void main(String[] args) {
        // 實現其餘運算只須要更改輸入的運算符便可
        BaseOperation operation = OperationFactory.createOperation("+");
        operation.setNumA(10);
        operation.setNumB(2);
        System.out.println("加法:" + operation.getResult());
    }

}

相比普通實現方式的好處

將每種運算的具體實現分離在不一樣的類中,工廠類只須要負責根據輸入的運算符來建立對應的運算類實例便可。好比要一個開方運算是吧,那麼須要建立一個開方運算類,一樣繼承BaseOperation,接着在工廠類中switch中添加一個case分支,而後客戶端便可以跟其餘運算同樣調用。
可能有人會問,這裏不也一樣是修改了switch分支條件嗎?有什麼區別?問得好,說明有思考過,可是緣由也很明顯,要仔細想一想。把四種基礎運算具體實現分離出去,工廠類中就包含了四行建立實例的代碼,這時修改了switch分支的風險,和普通實現方式的風險相比,哪一個大已經不用細說了吧。編碼

總結

這裏案例代碼比較簡單,因此看起來會很是明朗,想必沒必要多說讀者應該也能稍有體會。假如每一個類型的運算很是複雜,甚至與其餘模塊關聯,那使用設計模式的好處就體現出來了,比起所有代碼堆在一個switch case上,在單獨的一個類裏面會更好維護和擴展吧?想作到徹底不修改switch的代碼是不可能,最重要的是咱們達到了鬆耦合、可複用、可擴展目的,同時還下降了風險,有何不可。設計

相關文章
相關標籤/搜索