設計模式的七大原則(5) --開閉原則

前言

我們已經學習了單一職責原則,依賴倒置原則,接口隔離原則,李氏替換原則。可以說前面幾個原則都是爲了開閉原則奠定基礎。

我們寫的程序由於實際的情況可以一定程度上違背各種設計原則。但是,開閉原則我認爲作爲一個程序猿無論什麼時候都需要遵循他,切記不可違揹她。

基本介紹

  1. 開閉原則(Open Closed Principle)是編程中最基礎、最重要的設計原則
  2. 一個軟件實體如類,模塊和函數應該對擴展開放(對提供方),對修改關閉(對使用方)。用抽象構建框架,用實現擴展細節。
  3. 當軟件需要變化時,儘量通過擴展軟件實體的行爲來實現變化,而不是通過修改已 有的代碼來實現變化。
  4. 編程中遵循其它原則,以及使用設計模式的目的就是遵循開閉原則

那麼翻譯成通俗的話就是:

對修改關閉,對擴展開放。舉個例子,當我們要添加功能的時候,我們希望的是不修改的原有的代碼。而是對代碼進行一種擴展。後續我們用代碼示例。

這個原則更像是前四個原則甚至是所有原則的總綱,只要我們儘量的遵守其他的設計原則,那麼設計出來的系統應該就比較符合開閉原則了,相反,如果你違背了太多,那麼你的系統或許也不太遵循開閉原則。

案例

我們先來看一個反例

public class test {
    public static void main(String[] args) {
        Paintbrush graphicEditor = new Paintbrush();
        Shape rectangle = new Rectangle();
        Shape circle = new Circle();
        graphicEditor.drawShape(rectangle);
        graphicEditor.drawShape(circle);
    }
}

class Paintbrush {
    public void drawShape(Shape s) {
        if (s.m_type == 1)
            drawRectangle(s);
        else if (s.m_type == 2)
            drawCircle(s);
    }

    private void drawRectangle(Shape r) {
        System.out.println(" 矩形 ");

    }

    private void drawCircle(Shape r) {
        System.out.println(" 圓形 ");

    }

}

class Shape {
    int m_type;

}

class Rectangle extends Shape {
    Rectangle() {
        super.m_type = 1;
    }

}

class Circle extends Shape {
    Circle() {
        super.m_type = 2;

    }

}

我們這裏有一個畫筆類,裏面有一個繪畫方法,根據傳入的圖形來判斷具體畫出哪個畫。

咋一看這個類還不錯,比較好理解,簡單易操作。但是!但是!這個類的設計有一個很大的問題。違反了設計模式的開閉原則,即對擴展開放(提供方),對修改關閉(使用方)。

比如我們這時要新增加一個圖形種類三角形,我們要修改畫筆的源碼,添加一個判斷,如果這樣設計在我們平常項目開發中是非常坑爹的。

改進

我們對上面的代碼做一個改進,讓她遵循開閉原則。

思路:把創建Shape類做成抽象類,並提供一個抽象的draw方法,讓子類去實現即可, 這樣我們有新的圖形種類時,只需要讓新的圖形類繼承Shape,並實現draw方法即可, 使用方的代碼就不需要修 -> 滿足了開閉原則

public class test {
    public static void main(String[] args) {
        Paintbrush graphicEditor = new Paintbrush();
        Shape rectangle = new Rectangle();
        Shape circle = new Circle();
        Shape triangle  = new Triangle();
        Shape otherGraphic = new OtherGraphic();
        graphicEditor.drawShape(rectangle);
        graphicEditor.drawShape(circle);
        graphicEditor.drawShape(triangle);
        graphicEditor.drawShape(otherGraphic);
    }
}

class Paintbrush {
    public void drawShape(Shape s) {
        s.draw();
    }

}

abstract class Shape {
    int m_type;

    public abstract void draw();

}

class Rectangle extends Shape {
    Rectangle() {
        super.m_type = 1;
    }

    @Override
    public void draw() {
        System.out.println(" 矩形 ");
    }
}

class Circle extends Shape {
    Circle() {
        super.m_type = 2;
    }

    @Override
    public void draw() {
        System.out.println(" 圓形 ");
    }

}

class Triangle extends Shape {
    Triangle() {
        super.m_type = 3;
    }

    @Override
    public void draw() {
        System.out.println(" 三角形");
    }
}

class OtherGraphic extends Shape {
    OtherGraphic() {
        super.m_type = 4;
    }

    @Override
    public void draw() {
        System.out.println(" 其他圖形");
    }
}

通過這樣的修改,我們以後每次新增一個圖形不需要再做任何的修改,只需要new一個我們需要的圖形,繼承Shape類,實現繪畫方法即可。

希望大家細細體會,什麼是對修改關閉,對修改關閉,對擴展開放

總結

開閉原則是我們代碼實現中最最基礎,最最重要的原則。看一個人的代碼功底是否優秀,你就可以看他寫的代碼是否是遵循這個原則的。如果連這個原則都不遵循的代碼,我相信,後期的維護你自己都會罵娘。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章