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

  • 2019 年 10 月 3 日
  • 筆記

前言

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

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

基本介紹

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

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

總結

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