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

正號先生發表於2019-08-12

前言

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

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

基本介紹

  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類,實現繪畫方法即可。

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

總結

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

相關文章