https://blog.csdn.net/weixin_44036154/article/details/109026656
目錄:
在軟件開發中,為了提高軟件系統的可維護性和可復用性,增加軟件的可擴展性和靈活性,程序員要盡量根據 7 條原則來開發程序,從而提高軟件開發效率、節約軟件開發成本和維護成本。
這 7 種設計原則是軟件設計模式必須盡量遵循的原則,各種原則要求的側重點不同。其中,開閉原則是總綱,它告訴我們要對擴展開放,對修改關閉;里氏替換原則告訴我們不要破壞繼承體系;依賴倒置原則告訴我們要面向接口編程;單一職責原則告訴我們實現類要職責單一;接口隔離原則告訴我們在設計接口的時候要精簡單一;迪米特法則告訴我們要降低耦合度;合成復用原則告訴我們要優先使用組合或者聚合關系復用,少用繼承關系復用。
1、開閉原則
(1)原則定義:
軟件實體應當對擴展開放,對修改關閉,這就是開閉原則的經典定義。
這里的軟件實體包括以下幾個部分:
- 項目中划分出的模塊
- 類與接口
- 方法
(2)實現原理:
(3)實例展示:
/** * 定義課程接口 */ public interface ICourse { String getName(); // 獲取課程名稱 Double getPrice(); // 獲取課程價格 Integer getType(); // 獲取課程類型 } /** * 英語課程接口實現 */ public class EnglishCourse implements ICourse { private String name; private Double price; private Integer type; //省略get,set,空參,滿參 } // 測試 public class Main { public static void main(String[] args) { ICourse course = new EnglishCourse("小學英語", 199D, "Mr.Zhang"); System.out.println( "課程名字:" + course.getName() + " " + "課程價格:" + course.getPrice() + " " + "課程作者:" + course.getAuthor() ); } }
項目上線,但是出現了節假日打折的情況出現,現在有以下這幾種方法去修改:
1:修改接口(不可取,修改接口時其他的代碼也得改!)
2:修改實現類(不可取,這樣會有兩個獲取價格的方法!)
3:擴展實現方法(可取,不改變原有代碼,功能可實現!)
直接添加一個子類 SaleEnglishCourse ,重寫 getPrice()方法,這個方案對源代碼沒有影響,符合開閉原則,所以是可執行的方案
public class SaleEnglishCourse extends EnglishCourse { public SaleEnglishCourse(String name, Double price, String author) { super(name, price, author); } @Override public Double getPrice() { return super.getPrice() * 0.85; } }
(4)開閉原則的作用
開閉原則是面向對象程序設計的終極目標,它使軟件實體擁有一定的適應性和靈活性的同時具備穩定性和延續性。具體來說,其作用如下。
1. 對軟件測試的影響
軟件遵守開閉原則的話,軟件測試時只需要對擴展的代碼進行測試就可以了,因為原有的測試代碼仍然能夠正常運行。
2. 可以提高代碼的可復用性
粒度越小,被復用的可能性就越大;在面向對象的程序設計中,根據原子和抽象編程可以提高代碼的可復用性。
3. 可以提高軟件的可維護性
遵守開閉原則的軟件,其穩定性高和延續性強,從而易於擴展和維護。
2、里氏替換原則
(1)原則定義:
繼承必須確保超類(被繼承的類稱為超類,繼承的類稱為子類)所擁有的性質在子類中仍然成立。
(2)實現原理:
1、子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法
4、覆寫或實現父類的方法時輸出結果可以被縮小
(3)實例展示:
1、子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法
2、子類可以有自己的個性
在繼承父類屬性和方法的同時,每個子類也都可以有自己的個性,在父類的基礎上擴展自己的功能。前面其實已經提到,當功能擴展時,子類盡量不要重寫父類的方法,而是另寫一個方法,所以對上面的代碼加以更改,使其符合里氏替換原則。
(略)
3、覆蓋或實現父類的方法時輸入參數可以被放大
當子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬松。
public class ParentClazz { public void say(String str) { System.out.println("parent execute say " + str); } } public class ChildClazz extends ParentClazz { public void say(CharSequence str) { System.out.println("child execute say " + str); } } // 執行結果: // parent execute say hello // parent execute say hello // 參數大小不一樣,一直用的都是string,父類的
4、覆寫或實現父類的方法時輸出結果可以被縮小
當子類的方法實現父類的抽象方法時,方法的后置條件(即方法的返回值)要比父類更嚴格。
public abstract class Father { public abstract Map hello(); } public class Son extends Father { @Override public Map hello() { HashMap map = new HashMap(); System.out.println("son execute"); return map; } }
(4)里氏替換的作用:
里氏替換原則是實現開閉原則的重要方式之一。
3、依賴倒置原則
(1)原則定義:
依賴倒置原則的原始定義為:高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象。其核心思想是:要面向接口編程,不要面向實現編程。
(2)實現原理:
依賴倒置原則的目的是通過要面向接口的編程來降低類間的耦合性,所以我們在實際編程中只要遵循以下4點,就能在項目中滿足這個規則。
-
變量的聲明類型盡量是接口或者是抽象類。
-
任何類都不應該從具體類派生。
-
使用繼承時盡量遵循里氏替換原則。
(3)實例展示
public class T2 { public static void main(String[] args) { IDriver zhangsan = new Driver(); Icar benz = new Benz(); zhangsan.drive(benz); Icar bmw = new BMW(); zhangsan.drive(bmw); } } interface IDriver { // 司機職責就是駕駛汽車 public void drive(Icar car); } class Driver implements IDriver { // 司機職責就是駕駛汽車 @Override public void drive(Icar car) { car.run(); } } interface Icar { // 車的作用就是跑 public void run(); } class Benz implements Icar { // 車的作用就是跑 @Override public void run() { System.out.println("奔馳車跑起來了"); } } class BMW implements Icar { // 車的作用就是跑 @Override public void run() { System.out.println("寶馬車跑起來了"); } }
依賴倒置原則的主要作用如下。
-
依賴倒置原則可以提高系統的穩定性。
-
依賴倒置原則可以減少並行開發引起的風險。
-
依賴倒置原則可以提高代碼的可讀性和可維護性。