設計模式的七大原則(5) –開閉原則
- 2019 年 10 月 3 日
- 筆記
前言
我們已經學習了單一職責原則,依賴倒置原則,接口隔離原則,李氏替換原則。可以說前面幾個原則都是為了開閉原則奠定基礎。
我們寫的程序由於實際的情況可以一定程度上違背各種設計原則。但是,開閉原則我認為作為一個程序猿無論什麼時候都需要遵循他,切記不可違背她。
基本介紹
- 開閉原則(Open Closed Principle)是編程中最基礎、最重要的設計原則
- 一個軟件實體如類,模塊和函數應該對擴展開放(對提供方),對修改關閉(對使用方)。用抽象構建框架,用實現擴展細節。
- 當軟件需要變化時,盡量通過擴展軟件實體的行為來實現變化,而不是通過修改已 有的代碼來實現變化。
- 編程中遵循其它原則,以及使用設計模式的目的就是遵循開閉原則
那麼翻譯成通俗的話就是:
對修改關閉,對擴展開放。舉個例子,當我們要添加功能的時候,我們希望的是不修改的原有的代碼。而是對代碼進行一種擴展。後續我們用代碼示例。
這個原則更像是前四個原則甚至是所有原則的總綱,只要我們盡量的遵守其他的設計原則,那麼設計出來的系統應該就比較符合開閉原則了,相反,如果你違背了太多,那麼你的系統或許也不太遵循開閉原則。
案例
我們先來看一個反例
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類,實現繪畫方法即可。
希望大家細細體會,什麼是對修改關閉,對修改關閉,對擴展開放
總結
開閉原則是我們代碼實現中最最基礎,最最重要的原則。看一個人的代碼功底是否優秀,你就可以看他寫的代碼是否是遵循這個原則的。如果連這個原則都不遵循的代碼,我相信,後期的維護你自己都會罵娘。