程式設計七大原則
一、開閉原則
? 針對我們設計的功能模塊對擴展開放,對修改關閉:利用面向介面(抽象)編程(多型的特性),實作對功能需求擴展的同時,不允許更改原來的代碼,提高物件的可復用性、可維護性、靈活性,
? 抽象的說,用抽象思維構建我們想要創建的物體物件,用具體實作去擴展物體物件的細節實作,
? 具體的說,業務需求的功能可以去擴展,但是已經實作的功能不應該去修改,
-
需求:以簡單工廠模式和工廠方法模式理解開閉原則,
-
分析:
-
工廠模式是獲取一個實體物件的建造者模式,我們不關心物件如何產生,只關心結果,
-
簡單工廠模式是面對比較簡單的業務場景,用于獲取一個物件實體,我們需要傳入相關業務引數,讓簡單工廠物件去做相應的判斷,然后回傳給我們對應的實體物件,這個工廠物件做了很多事情,他違背了單一職責原則,當我們的業務需要擴展的時候,這個工廠物件必須去修改,新增業務判斷,新增回傳對應的實體物件,這就違背了開閉原則,
public class FruitsFactory { /** * @description: * @param fruitsName * @return com.lmc.gp13280.pattern.factory.fruits.IFruits * @date 2019/5/23 15:44 * @author lmc */ public IFruits product(String fruitsName){ if(null != fruitsName && fruitsName != ""){ System.out.println("客戶需求的水果是"+fruitsName); if("蘋果".equals(fruitsName)){ System.out.println("水果工廠生產了蘋果"); return new Apple(); } if("橙子".equals(fruitsName)){ System.out.println("水果工廠生產了橙子"); return new Orange(); } if("香蕉".equals(fruitsName)){ System.out.println("水果工廠生產了香蕉"); return new Banana(); } return null; }else{ return null; } } }上面是一個水果工廠,我如果想要草莓,就必須的修改代碼去實作草莓的生產了,
-
工廠方法模式是抽象一個工廠介面,讓具體的工廠子類實體物件實作工廠介面,我們想要一個具體的實體物件,只需要找相應的子類工廠實作類就可以了,如果需要業務擴展,我們不需要修改原來的工廠子類,只需要新增新的工廠子類就行了,這就實作了業務擴展,但是不會修改原來的程式邏輯,遵循了開閉原則和單一職責原則,
public interface IFruitsFactory { /** * 工廠的生產方法 * @return IFruits */ IFruits product(); }public class AppleFactory implements IFruitsFactory { @Override public IFruits product() { System.out.println("蘋果工廠只生產蘋果"); return new Apple(); } }public class BananaFactory implements IFruitsFactory { @Override public IFruits product() { System.out.println("香蕉工廠只生產香蕉"); return new Banana(); } }public class OrangeFactory implements IFruitsFactory { @Override public IFruits product() { System.out.println("橙子工廠只生產橙子"); return new Orange(); } }上面的示例代碼中,我們要新增具體的水果工廠去擴展業務,只需要新增對應的工廠子類去實作水果工廠的介面就行了,
-
實作業務擴展,不改變原來的程式就是遵循開閉原則,
-
二、依賴倒置原則
? spring的依賴注入相信大家都不陌生,其實依賴倒置原則是程式物件依賴其他物件的時候,應該依賴其抽象,不要依賴實作,應該依賴頂層物件,不要依賴具體的底層物件,因為程式的具體實作都是實作類去實作的,但是我們要去依賴實作類的頂層介面物件,這就是倒置,也就是依賴倒置,
? 依賴倒置原則的核心是運行時多型,程式在編譯時不會去實體化子類物件,在程式運行的時候虛擬機才會去選擇實體化具體的子類物件,
? 在程式設計中,一般介面定義好了,就不會去輕易改變,因為,在一個成熟的系統中,改變介面,就相當于把設計推翻重構了,你愿意做這樣的事情?但是實作類,咱們可以進行輕微改動,或者說不改,新增一個新的實作類去代替,如果依賴其實作類,只要實作類改動,那么程式員的災難是不是來了呢?如果依賴其頂層介面,我們其他依賴此介面的代碼都不需要去做任何改動,因為介面沒變啊,只需要改動需求具體的實作業務邏輯,或者新增業務子類實作介面,是不是可以提前下班了,
? 通過依賴倒置,可以減少類與類之間的耦合性,提高系統的穩定性,提高代碼的
可讀性和可維護性,并能夠降低修改程式所造成的風險,
/**
* 水果店
* @author: maocheng.liao
* @create: 2020-02-23 15:20
*/
public class FruitShop {
private IFruitsFactory fruitsFactory;
public IFruitsFactory getFruitsFactory() {
return fruitsFactory;
}
public void setFruitsFactory(IFruitsFactory fruitsFactory) {
this.fruitsFactory = fruitsFactory;
}
/**
* @description:
* @param :從水果生產基地去進貨水果
* @return com.lmc.gp13280.pattern.factory.fruits.IFruits
* @date 2020/2/23 15:34
* @author maocheng.liao
*/
public IFruits getFruits(){
IFruits fruits = fruitsFactory.product();
return fruits;
}
}
/**
* 水果店依賴倒置測驗
*
* @author: maocheng.liao
* @create: 2020-02-23 15:25
*/
public class FruitShopTest {
public static void main(String[] args) {
IFruitsFactory fruitsFactory= new AppleFactory();
FruitShop fruitShop=new FruitShop();
fruitShop.setFruitsFactory(fruitsFactory);
IFruits apple = fruitShop.getFruits();
apple.getName();
fruitsFactory = new BananaFactory();
fruitShop.setFruitsFactory(fruitsFactory);
IFruits banana = fruitShop.getFruits();
banana.getName();
fruitsFactory = new OrangeFactory();
fruitShop.setFruitsFactory(fruitsFactory);
IFruits orange = fruitShop.getFruits();
orange.getName();
}
}
上面的代碼就是最簡單的依賴倒置的實作,我們依賴的是水果工廠介面和水果介面,水果店是在水果生產基地去進貨水果,至于進貨什么水果,取決于水果生產基地生產什么水果和水果店想進什么水果,而不是依賴具體的水果工廠實作類和具體的水果實作類,
- 注意:上述部分簡單代碼并未呈現,詳細代碼見博客地址:https://www.cnblogs.com/programmerkaixin/p/10918844.html
三、單一職責原則
? 我覺得單一職責是迪米特法則的一種體現,
? 單一職責原則:見名知意,專人做專事,不要多管閑事,對于類、介面、方法只負責一項自己的職責,對于自己的職責程式修改之后,不會影響到其的職責程式,高內聚,低耦合的程式必須遵循單一職責,分工明確,可讀性、可維護性高,
? 最簡單的示例:咱們人的手腳代替不了眼睛,眼睛也代替不了手腳,
? 臃腫這個詞是不是能很好的體現出單一職責原則呢?代碼寫的這么臃腫,還能不能好好玩耍啦,
四、介面隔離原則
? 我覺得介面隔離原則是單一職責原則的一種體現,也是迪米特法則的一種體現,
? 面向物件編程,萬物皆物件,
? 介面隔離原則:定義多個細化而明確分工的專門介面,不要去定義一個單一臃腫的介面,對于臃腫的介面,我們不好具體實作,這樣肯定會違背單一職責原則,
? 最簡單的示例:對于家用小汽車物件來說,往大的說,他屬于交通工具類、他屬于車類、它屬于汽車類,往小的說,它屬于家用小汽車類、私家車類,
?
五、迪米特法則
? 迪米特法則又叫最少知道原則,也有單一職責和介面隔離原則的味道,
? 迪米特法則:低耦合,如何做到極致呢,那就是只依賴自己真正有關系的物件,在我職責之外的物件全部拒之門外,
? 我覺得這個沒啥好說的,做到了單一職責,迪米特法則很好實作吧,
六、里氏替換原則
? 官方定義:任何基類(父類)可以出現的地方,子類一定可以出現, 里氏替換原則是繼承復用的基石,只有當衍生類可以替換掉基類,軟體單位的功能不受到影響時,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為,當一個子類的實體應該能夠替換任何其超類的實體時,它們之間才具有is-A關系,
? 本人理解: 里氏替換原則是為了約束繼承泛濫,就是說,在面向物件程式設計中,必須具有is-A的關系才能去使用繼承,而不能去為了實作某一業務需求,為了方便使用繼承而繼承,
? 前置條件:每個方法呼叫之前,該方法應該校驗傳入引數的正確性,只有正確才能執行該方法,否則認為呼叫方違反契約,不予執行,這稱為前置條件(Pre-condition),
? 后置條件:一旦通過前置條件的校驗,方法必須執行,并且必須確保執行結果符合契約,這稱之為后置條件(Post-condition),也就是回傳值符合,
? 里氏替換原則約束條件:當存在繼承關系時,子類中方法的前置條件必須與超類中被覆寫的方法的前置條件相同或者更寬松;而子類中方法的后置條件必須與超類中被覆寫的方法的后置條件相同或者更為嚴格,
? 不要為了繼承而繼承,而是真的有繼承關系的時候才能去繼承,
七、合成復用原則
? 這里結合依賴倒置原則使用合成復用原則效果更佳,
? 組合(has-a):類比電腦組裝,記憶體、硬碟、cpu、顯卡 ······ 它們之間組成了電腦,但是他們之間沒有什么關系,這就是組合關系,生命周期一致,
? 聚合(contanis-a):類比員工聚合成部門,員工和部門是相互獨立的,一兩個員工離職不影響部門物件,部門解散也不影響員工物件,
? 合成復用原則:程式復用盡量使用組合關系、聚合關系,盡量少使用繼承關系去實作業務需求,
? 繼承會把所有的實作全部暴露給子類,破壞了類的封裝性,父類的改變,會影響子類,高耦合,
? 組合、聚合可以很好的遵循依賴倒置原則,開閉原則,成員物件的細節實作(組合、聚合物件)對于一個新的物件是隱藏的,
? 合成復用原則配合依賴倒置原則,很好的遵循開閉原則,達到程式高可用、高可維、高可讀,
? spring為什么這么牛?spring為什么依賴注入?spring為什么是輕量級的?
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/12469.html
標籤:架構設計
上一篇:質量屬性
