摘要:六開閉原則開閉原則簡介開閉原則的英文名稱是,簡稱。開閉原則是面向?qū)ο笤O(shè)計中最基礎(chǔ)的設(shè)計原則,它指導(dǎo)我們?nèi)绾谓⒁粋€穩(wěn)定靈活的軟件系統(tǒng)。
面向?qū)ο蠡驹瓌t(3)- 最少知道原則與開閉原則
面向?qū)ο蠡驹瓌t(1)- 單一職責(zé)原則與接口隔離原則
面向?qū)ο蠡驹瓌t(2)- 里式代換原則與依賴倒置原則
面向?qū)ο蠡驹瓌t(3)- 最少知道原則與開閉原則
最少知識原則(Least KnowledgePrinciple,LKP)也稱為迪米特法則(Law of Demeter,LoD)。雖然名字不同,但描述的是同一個規(guī)則:一個對象應(yīng)該對其他對象有最少的了解。
通俗地講,一個類應(yīng)該對自己需要耦合或調(diào)用的類知道得最少,你(被耦合或調(diào)用的類)的內(nèi)部是如何復(fù)雜都和我沒關(guān)系,那是你的事情,我就知道你提供的這么多public方法,我就調(diào)用這么多,其他的我一概不關(guān)心。
2. 最少知道原則實(shí)現(xiàn) 只與直接關(guān)聯(lián)的類交流每個對象都必然會與其他對象有耦合關(guān)系,耦合關(guān)系的類型有很多,例如組合、聚合、依賴等。
出現(xiàn)在成員變量、方法的輸入輸出參數(shù)中的類稱為直接關(guān)聯(lián)的類,而出現(xiàn)在方法體內(nèi)部的類不屬于直接關(guān)聯(lián)的類。
下面舉例說明如何才能做到只與直接關(guān)聯(lián)的類交流。
場景:老師想讓班長清點(diǎn)女生的數(shù)量
Bad
/** * 老師類 * Class Teacher */ class Teacher { /** * 老師對班長發(fā)布命令,清點(diǎn)女生數(shù)量 * @param GroupLeader $groupLeader */ public function command(GroupLeader $groupLeader) { // 產(chǎn)生一個女生群體 $girlList = new ArrayIterator(); // 初始化女生 for($i = 0; $i < 20; $i++){ $girlList->append(new Girl()); } // 告訴班長開始執(zhí)行清點(diǎn)任務(wù) $groupLeader->countGirls($girlList); } } /** * 班長類 * Class GroupLeader */ class GroupLeader { /** * 清點(diǎn)女生數(shù)量 * @param ArrayIterator $girlList */ public function countGirls($girlList) { echo "女生數(shù)量是:", $girlList->count(), " "; } } /** * 女生類 * Class Girl */ class Girl { } $teacher= new Teacher(); //老師發(fā)布命令 $teacher->command(new GroupLeader()); // 女生數(shù)量是:20
上面實(shí)例中,Teacher類僅有一個直接關(guān)聯(lián)的類 -- GroupLeader。而Girl這個類就是出現(xiàn)在commond方法體內(nèi),因此不屬于與Teacher類直接關(guān)聯(lián)的類。
方法是類的一個行為,類竟然不知道自己的行為與其他類產(chǎn)生依賴關(guān)系,這是不允許的,違反了迪米特法則。
對程序進(jìn)行簡單的修改,把 對 $girlList 的初始化移出 Teacher 類,同時在 GroupLeader 中增加對 Girl 的注入,避開 Teacher 類對陌生類 Girl 的訪問,降低系統(tǒng)間的耦合,提高系統(tǒng)的健壯性。
下面是改進(jìn)后的代碼:
Good
/** * 老師類 * Class Teacher */ class Teacher { /** * 老師對班長發(fā)布命令,清點(diǎn)女生數(shù)量 * @param GroupLeader $groupLeader */ public function command(GroupLeader $groupLeader) { // 告訴班長開始執(zhí)行清點(diǎn)任務(wù) $groupLeader->countGirls(); } } /** * 班長類 * Class GroupLeader */ class GroupLeader { private $_girlList; /** * 傳遞全班的女生進(jìn)來 * GroupLeader constructor. * @param Girl[]|ArrayIterator $girlList */ public function __construct(ArrayIterator $girlList) { $this->_girlList = $girlList; } //清查女生數(shù)量 public function countGirls() { echo "女生數(shù)量是:", $this->_girlList->count(), " "; } } /** * 女生類 * Class Girl */ class Girl { } // 產(chǎn)生一個女生群體 $girlList = new ArrayIterator(); // 初始化女生 for($i = 0; $i < 20; $i++){ $girlList->append(new Girl()); } $teacher= new Teacher(); //老師發(fā)布命令 $teacher->command(new GroupLeader($girlList)); // 女生數(shù)量是:20關(guān)聯(lián)的類之間也要有距離
迪米特法則要求類“羞澀”一點(diǎn),盡量不要對外公布太多的public方法和非靜態(tài)的public變量,盡量內(nèi)斂,多使用private、protected等訪問權(quán)限。
一個類公開的public屬性或方法越多,修改時涉及的面也就越大,變更引起的風(fēng)險擴(kuò)散也就越大。因此,為了保持類間的距離,在設(shè)計時需要反復(fù)衡量:是否還可以再減少public方法和屬性,是否可以修改為private、protected等訪問權(quán)限,是否可以加上final關(guān)鍵字等。
實(shí)例場景:實(shí)現(xiàn)軟件安裝的過程,其中first方法定義第一步做什么,second方法定義第二步做什么,third方法定義第三步做什么。
Bad
/** * 導(dǎo)向類 * Class Wizard */ class Wizard { /** * 第一步 * @return int */ public function first() { echo "執(zhí)行第一步安裝... "; // 模擬用戶點(diǎn)是或取消 return rand(0, 1); } /** * 第二步 * @return int */ public function second() { echo "執(zhí)行第二步安裝... "; // 模擬用戶點(diǎn)是或取消 return rand(0, 1); } /** * 第三步 * @return int */ public function third() { echo "執(zhí)行第三步安裝... "; // 模擬用戶點(diǎn)是或取消 return rand(0, 1); } } /** * 安裝軟件類 * Class InstallSoftware */ class InstallSoftware { /** * 執(zhí)行安裝軟件操作 * @param Wizard $wizard */ public function installWizard(Wizard $wizard) { $first = $wizard->first(); //根據(jù)first返回的結(jié)果,看是否需要執(zhí)行second if($first === 1){ $second = $wizard->second(); if($second === 1){ $third = $wizard->third(); if($third === 1){ echo "軟件安裝完成! "; } } } } } // 實(shí)例化軟件安裝類 $invoker = new InstallSoftware(); // 開始安裝軟件 $invoker->installWizard(new Wizard()); // 運(yùn)行結(jié)果和隨機(jī)數(shù)有關(guān),每次的執(zhí)行結(jié)果都不相同
Wizard類把太多的方法暴露給InstallSoftware類,兩者的朋友關(guān)系太親密了,耦合關(guān)系變得異常牢固。如果要將Wizard類中的first方法返回值的類型由int改為boolean,就需要修改InstallSoftware類,從而把修改變更的風(fēng)險擴(kuò)散開了。因此,這樣的耦合是極度不合適的。
改進(jìn):在Wizard類中增加一個installWizard方法,對安裝過程進(jìn)行封裝,同時把原有的三個public方法修改為private方法。
/** * 導(dǎo)向類 * Class Wizard */ class Wizard { //第一步 private function first() { echo "執(zhí)行第1個方法... "; // 模擬用戶點(diǎn)是或取消 return rand(0, 1); } //第二步 private function second() { echo "執(zhí)行第2個方法... "; // 模擬用戶點(diǎn)是或取消 return rand(0, 1); } //第三個方法 private function third() { echo "執(zhí)行第3個方法... "; // 模擬用戶點(diǎn)是或取消 return rand(0, 1); } public function installWizard(){ $first = $this->first(); //根據(jù)first返回的結(jié)果,看是否需要執(zhí)行second if($first === 1){ $second = $this->second(); if($second === 1){ $third = $this->third(); if($third === 1){ echo "軟件安裝完成! "; } } } } } /** * 安裝軟件類 * Class InstallSoftware */ class InstallSoftware { /** * 執(zhí)行安裝軟件操作 * @param Wizard $wizard */ public function installWizard(Wizard $wizard) { $wizard->installWizard(); } } // 實(shí)例化軟件安裝類 $invoker = new InstallSoftware(); // 開始安裝軟件 $invoker->installWizard(new Wizard()); // 運(yùn)行結(jié)果和隨機(jī)數(shù)有關(guān),每次的執(zhí)行結(jié)果都不相同
代碼改進(jìn)后,類間的耦合關(guān)系變?nèi)趿?,結(jié)構(gòu)也清晰了,變更引起的風(fēng)險也變小了。
3. 最佳實(shí)踐在實(shí)際應(yīng)用中經(jīng)常會出現(xiàn)這樣一個方法:放在本類中也可以,放在其他類中也沒有錯,那怎么去衡量呢?
你可以堅持這樣一個原則:如果一個方法放在本類中,既不增加類間關(guān)系,也對本類不產(chǎn)生負(fù)面影響,那就放置在本類中。
在實(shí)際應(yīng)用中,如果一個類跳轉(zhuǎn)兩次以上才能訪問到另一個類,就需要想辦法進(jìn)行重構(gòu)了。
因?yàn)橐粋€系統(tǒng)的成功不僅僅是一個標(biāo)準(zhǔn)或是原則就能夠決定的,有非常多的外在因素決定,跳轉(zhuǎn)次數(shù)越多,系統(tǒng)越復(fù)雜,維護(hù)就越困難,所以只要跳轉(zhuǎn)不超過兩次都是可以忍受的,這需要具體問題具體分析。
迪米特法則要求類間解耦,但解耦是有限度的,除非是計算機(jī)的最小單元——二進(jìn)制的0和1。那才是完全解耦,在實(shí)際的項(xiàng)目中,需要適度地考慮這個原則,別為了套用原則而做項(xiàng)目。
原則只是供參考,如果違背了這個原則,項(xiàng)目也未必會失敗,這就需要大家在采用原則時反復(fù)度量,不遵循是不對的,嚴(yán)格執(zhí)行就是“過猶不及”。
開閉原則的英文名稱是 Open-Close Principle,簡稱OCP。
開閉原則是面向?qū)ο笤O(shè)計中最基礎(chǔ)的設(shè)計原則,它指導(dǎo)我們?nèi)绾谓⒁粋€穩(wěn)定、靈活的軟件系統(tǒng)。
開閉原則的英文定義是
Software entities like classes,modules and functions should be open for extension but closed for modifications.
一個軟件實(shí)體如類、模塊和函數(shù)應(yīng)該對擴(kuò)展開放,對修改關(guān)閉。 其含義是說一個軟件實(shí)體應(yīng)該通過擴(kuò)展來實(shí)現(xiàn)變化,而不是通過修改已有的代碼來實(shí)現(xiàn)變化。
軟件實(shí)體包括以下幾個部分:
項(xiàng)目或軟件產(chǎn)品中按照一定的邏輯規(guī)則劃分的模塊。
抽象和類。
方法。
一個軟件產(chǎn)品只要在生命期內(nèi),都會發(fā)生變化,既然變化是一個既定的事實(shí),我們就應(yīng)該在設(shè)計時盡量適應(yīng)這些變化,以提高項(xiàng)目的穩(wěn)定性和靈活性,真正實(shí)現(xiàn)“擁抱變化”。開閉原則告訴我們應(yīng)盡量通過擴(kuò)展軟件實(shí)體的行為來實(shí)現(xiàn)變化,而不是通過修改已有的代碼來完成變化,它是為軟件實(shí)體的未來事件而制定的對現(xiàn)行開發(fā)設(shè)計進(jìn)行約束的一個原則。
2. 開閉原則的優(yōu)點(diǎn) 提高復(fù)用率在面向?qū)ο蟮脑O(shè)計中,所有的邏輯都是從原子邏輯組合而來的,而不是在一個類中獨(dú)立實(shí)現(xiàn)一個業(yè)務(wù)邏輯。只有這樣代碼才可以復(fù)用,粒度越小,被復(fù)用的可能性就越大。
復(fù)用可以減少代碼量,避免相同的邏輯分散在多個角落,避免日后的維護(hù)人員為了修改一個微小的缺陷或增加新功能而要在整個項(xiàng)目中到處查找相關(guān)的代碼。
那怎么才能提高復(fù)用率呢?縮小邏輯粒度,直到一個邏輯不可再拆分為止。
一款軟件投產(chǎn)后,維護(hù)人員的工作不僅僅是對數(shù)據(jù)進(jìn)行維護(hù),還可能要對程序進(jìn)行擴(kuò)展,維護(hù)人員最樂意做的事情就是擴(kuò)展一個類,而不是修改一個類,甭管原有的代碼寫得多么優(yōu)秀還是多么糟糕,讓維護(hù)人員讀懂原有的代碼,然后再修改,是一件很痛苦的事情,不要讓他在原有的代碼海洋里游弋完畢后再修改,那是對維護(hù)人員的一種折磨和摧殘。
面向?qū)ο箝_發(fā)的要求萬物皆對象,我們需要把所有的事物都抽象成對象,然后針對對象進(jìn)行操作,但是萬物皆運(yùn)動,有運(yùn)動就有變化,有變化就要有策略去應(yīng)對。怎么快速應(yīng)對呢?這就需要在設(shè)計之初考慮到所有可能變化的因素,然后留下接口,等待“可能”轉(zhuǎn)變?yōu)椤艾F(xiàn)實(shí)”。
2. 變化的三種類型 邏輯變化只變化一個邏輯,而不涉及其他模塊,比如原有的一個算法是 a*b+c,現(xiàn)在需要修改為 a*b*c,可以通過修改原有類中的方法的方式來完成,前提條件是所有依賴或關(guān)聯(lián)類都按照相同的邏輯處理。
子模塊變化一個模塊變化,會對其他的模塊產(chǎn)生影響,特別是一個低層次的模塊變化必然引起高層模塊的變化,因此在通過擴(kuò)展完成變化時,高層次的模塊修改是必然的,剛剛的書籍打折處理就是類似的處理模塊,該部分的變化甚至?xí)鸾缑娴淖兓?/p> 視圖變化
可見視圖是提供給客戶使用的界面,該部分的變化一般會引起連鎖反應(yīng)。如果僅僅是界面上按鈕、文字的重新排布倒是簡單,最司空見慣的是業(yè)務(wù)耦合變化,例如一個展示數(shù)據(jù)的列表,按照原有的需求是6列,突然有一天要增加1列,而且這一列要跨N張表,處理M個邏輯才能展現(xiàn)出來,這樣的變化是比較恐怖的,但還是可以通過擴(kuò)展來完成變化,這就要看我們原有的設(shè)計是否靈活。
3. 開閉原則的使用 抽象約束抽象是對一組事物的通用描述,沒有具體的實(shí)現(xiàn),也就表示它可以有非常多的可能性,可以跟隨需求的變化而變化。因此,通過接口或抽象類可以約束一組可能變化的行為,并且能夠?qū)崿F(xiàn)對擴(kuò)展開放,其包含三層含義:
第一,通過接口或抽象類約束擴(kuò)展,對擴(kuò)展進(jìn)行邊界限定,不允許出現(xiàn)在接口或抽象類中不存在的public方法;
第二,參數(shù)類型、引用對象盡量使用接口或者抽象類,而不是實(shí)現(xiàn)類;
第三,抽象層盡量保持穩(wěn)定,一旦確定即不允許修改。
對變化的封裝包含兩層含義:
第一,將相同的變化封裝到一個接口或抽象類中;
第二,將不同的變化封裝到不同的接口或抽象類中,不應(yīng)該有兩個不同的變化出現(xiàn)在同一個接口或抽象類中。
封裝變化,也就是受保護(hù)的變化(protected variations),找出預(yù)計有變化或不穩(wěn)定的點(diǎn),我們?yōu)檫@些變化點(diǎn)創(chuàng)建穩(wěn)定的接口,準(zhǔn)確地講是封裝可能發(fā)生的變化,一旦預(yù)測到或“第六感”發(fā)覺有變化,就可以進(jìn)行封裝。
代碼使用PHP7.2語法編寫
書籍接口
/** * Interface IBook * 書籍接口 */ interface IBook { /** * 書籍名稱 * @return mixed */ public function getName() : string ; /** * 書籍價格 * 這里把價格定義為int類型并不是錯誤, * 在非金融類項(xiàng)目中對貨幣處理時,一般取2位精度, * 通常的設(shè)計方法是在運(yùn)算過程中擴(kuò)大100倍,在需要展示時再縮小100倍,減少精度帶來的誤差。 * @return mixed */ public function getPrice() : int ; /** * 書籍作者 * @return mixed */ public function getAuthor() : string ; }
小說類
/** * 小說類 * Class NovelBook */ class NovelBook implements IBook { /** * 書籍名稱 * @var string $_name */ private $_name; /** * 書籍價格 * @var int $_price */ private $_price; /** * 書籍作者 * @var string $_author */ private $_author; /** * 通過構(gòu)造函數(shù)傳遞書籍信息 * @param string $name * @param int $price * @param string $author */ public function __construct(string $name, int $price, string $author) { $this->_name = $name; $this->_price = $price; $this->_author = $author; } /** * 獲取書籍名稱 * @return string */ public function getName() : string { return $this->_name; } /** * 獲取書籍價格 * @return int */ public function getPrice() : int { return $this->_price; } /** * 獲取書籍作者 * @return string */ public function getAuthor() : string { return $this->_author; } }
售書場景
// 產(chǎn)生一個書籍列表 $bookList = new ArrayIterator(); // 始化數(shù)據(jù) $bookList->append(new NovelBook("天龍八部",3200,"金庸")); $bookList->append(new NovelBook("巴黎圣母院",5600,"雨果")); echo "------書店賣出去的書籍記錄如下:-------- "; foreach($bookList as $book){ $price = $book->getPrice() / 100; echo <<getName()} 書籍作者: {$book->getAuthor()} 書籍價格: {$price} 元 --- TXT; }
------書店賣出去的書籍記錄如下:-------- 書籍名稱: 天龍八部 書籍作者: 金庸 書籍價格: 32 元 --- 書籍名稱: 巴黎圣母院 書籍作者: 雨果 書籍價格: 56 元 ---
一段時間之后,書店決定對小說類書籍進(jìn)行打折促銷:所有40元以上的書籍9折銷售,其他的8折銷售。面對需求的變化,我們有兩種解決方案。
修改實(shí)現(xiàn)類NovelBook
直接修改NovelBook類中的getPrice()方法實(shí)現(xiàn)打折處理。該方法在項(xiàng)目有明確的章程(團(tuán)隊內(nèi)約束)或優(yōu)良的架構(gòu)設(shè)計時,是一個非常優(yōu)秀的方法,但是該方法還是有缺陷的。例如采購書籍人員也是要看價格的,由于該方法已經(jīng)實(shí)現(xiàn)了打折處理價格,因此采購人員看到的也是打折后的價格,會因信息不對稱而出現(xiàn)決策失誤的情況。
通過擴(kuò)展實(shí)現(xiàn)變化
增加一個子類OffNovelBook,覆寫getPrice方法,高層次的模塊通過OffNovelBook類產(chǎn)生新的對象,完成業(yè)務(wù)變化對系統(tǒng)的最小化開發(fā),修改少,風(fēng)險也小。
打折銷售的小說類
/** * 打折銷售的小說類 * Class OffNovelBook */ class OffNovelBook extends NovelBook { /** * 覆寫獲取銷售價格方法 * * @return int */ public function getPrice() : int { //原價 $originPrice = parent::getPrice(); if($originPrice > 40){ //原價大于40元,則打9折 $discountPrice = $originPrice * 90 / 100; }else{ $discountPrice = $originPrice * 80 / 100; } return $discountPrice; } }
打折售書場景
// 產(chǎn)生一個書籍列表 $bookList = new ArrayIterator(); // 始化數(shù)據(jù),實(shí)際項(xiàng)目中一般是由持久層完成 $bookList->append(new OffNovelBook("天龍八部",3200,"金庸")); $bookList->append(new OffNovelBook("巴黎圣母院",5600,"雨果")); echo "------書店賣出去的書籍記錄如下:------ "; foreach($bookList as $book){ $price = $book->getPrice() / 100; echo <<getName()} 書籍作者: {$book->getAuthor()} 書籍價格: {$price} 元 --- TXT; }
------書店賣出去的書籍記錄如下:------ 書籍名稱: 天龍八部 書籍作者: 金庸 書籍價格: 28.8 元 --- 書籍名稱: 巴黎圣母院 書籍作者: 雨果 書籍價格: 50.4 元 ---
又過了一段時間,書店新增加了計算機(jī)書籍,它不僅包含書籍名稱、作者、價格等信息,還有一個獨(dú)特的屬性:面向的是什么領(lǐng)域,也就是它的范圍,比如是和編程語言相關(guān)的,還是和數(shù)據(jù)庫相關(guān)的,等等。
增加一個IComputerBook接口,它繼承自IBook
/** * 計算機(jī)類書籍接口 * Interface IComputerBook */ interface IComputerBook extends IBook { /** * 計算機(jī)書籍增加一個范圍屬性 * @return string */ public function getScope() : string ; }
計算機(jī)書籍類
/** * 計算機(jī)書籍類 * Class ComputerBook */ class ComputerBook implements IComputerBook { /** * 書籍名稱 * @var string $_name */ private $_name; /** * 書籍價格 * @var int $_price */ private $_price; /** * 書籍作者 * @var string $_author */ private $_author; /** * 書籍范圍 * @var string $_scope */ private $_scope; /** * 通過構(gòu)造函數(shù)傳遞書籍信息 * ComputerBook constructor. * @param string $name * @param int $price * @param string $author * @param string $scope */ public function __construct(string $name, int $price, string $author, string $scope) { $this->_name = $name; $this->_price = $price; $this->_author = $author; $this->_scope = $scope; } /** * 獲取書籍名稱 * @return string */ public function getName() : string { return $this->_name; } /** * 獲取書籍價格 * @return int */ public function getPrice() : int { return $this->_price; } /** * 獲取書籍作者 * @return string */ public function getAuthor() : string { return $this->_author; } /** * 獲取書籍范圍 * @return string */ public function getScope() : string { return $this->_scope; } }
增加計算機(jī)書籍銷售
//產(chǎn)生一個書籍列表 $bookList = new ArrayIterator(); // 始化數(shù)據(jù),實(shí)際項(xiàng)目中一般是由持久層完成 $bookList->append(new OffNovelBook("天龍八部",3200,"金庸")); $bookList->append(new OffNovelBook("巴黎圣母院",5600,"雨果")); $bookList->append(new ComputerBook("高性能MySQL",4800,"Baron", "數(shù)據(jù)庫")); echo "------書店賣出去的書籍記錄如下:------ "; foreach($bookList as $book) { $price = $book->getPrice() / 100; echo <<getName()} 書籍作者: {$book->getAuthor()} 書籍價格: {$price} 元 --- TXT; }
------書店賣出去的書籍記錄如下:------ 書籍名稱: 天龍八部 書籍作者: 金庸 書籍價格: 28.8 元 --- 書籍名稱: 巴黎圣母院 書籍作者: 雨果 書籍價格: 50.4 元 --- 書籍名稱: 高性能MySQL 書籍作者: Baron 書籍價格: 48 元 ---
開閉原則對擴(kuò)展開放,對修改關(guān)閉,并不意味著不做任何修改,低層模塊的變更,必然要有高層模塊進(jìn)行耦合,否則就是一個孤立無意義的代碼片段。
參考文獻(xiàn):《設(shè)計模式之禪》
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/31601.html
摘要:面向?qū)ο蠡驹瓌t單一職責(zé)原則與接口隔離原則面向?qū)ο蠡驹瓌t單一職責(zé)原則與接口隔離原則面向?qū)ο蠡驹瓌t里式代換原則與依賴倒置原則面向?qū)ο蠡驹瓌t最少知道原則與開閉原則一單一職責(zé)原則單一職責(zé)原則簡介單一職責(zé)原則的英文名稱是,簡稱。 面向?qū)ο蠡驹瓌t(1)- 單一職責(zé)原則與接口隔離原則 面向?qū)ο蠡驹瓌t(1)- 單一職責(zé)原則與接口隔離原則面向?qū)ο蠡驹瓌t(2)- 里式代換原則與依賴倒置原則面...
摘要:四依賴倒置原則依賴倒置原則簡介依賴倒置原則的英文名稱是,簡稱。依賴倒置原則的表現(xiàn)其實(shí)就是面向接口編程。依賴倒置原則的優(yōu)點(diǎn)減少類間的耦合性,提高系統(tǒng)的穩(wěn)定性。結(jié)合里氏替換原則使用接口負(fù)責(zé)定義屬性和方法,并且聲明與其他對象的依賴關(guān)系。 面向?qū)ο蠡驹瓌t(2)- 里式代換原則與依賴倒置原則 面向?qū)ο蠡驹瓌t(1)- 單一職責(zé)原則與接口隔離原則面向?qū)ο蠡驹瓌t(2)- 里式代換原則與依賴倒置原...
摘要:單一職責(zé)原則開閉原則里氏替換原則依賴倒置原則接口隔離原則迪米特法則組合聚合復(fù)用原則單一職責(zé)原則高內(nèi)聚低耦合定義不要存在多于一個導(dǎo)致類變更的原因。建議接口一定要做到單一職責(zé),類的設(shè)計盡量做到只有一個原因引起變化。使用繼承時遵循里氏替換原則。 單一職責(zé)原則 開閉原則 里氏替換原則 依賴倒置原則 接口隔離原則 迪米特法則 組合/聚合復(fù)用原則 單一職責(zé)原則(Single Responsi...
摘要:依賴倒置原則是個設(shè)計原則中最難以實(shí)現(xiàn)的原則,它是實(shí)現(xiàn)開閉原則的重要途徑,依賴倒置原則沒有實(shí)現(xiàn),就別想實(shí)現(xiàn)對擴(kuò)展開放,對修改關(guān)閉。 1、單一職能原則(Single Responsibility Principle, SRP) 定義 There should never be more than one reason for a class to change.應(yīng)該有且僅有一個原因引起類的...
摘要:里氏替換原則里氏代換原則面向?qū)ο笤O(shè)計的基本原則之一。里氏代換原則中說,任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。里氏代換原則是對開閉原則的補(bǔ)充。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原則是對實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。 showImg(https://segmentfault.com/img/bVbuXAu?w=640&h=361); 本文為本次系列文章的第一篇,接下...
閱讀 1317·2021-09-26 09:55
閱讀 3380·2019-08-30 15:55
閱讀 1070·2019-08-30 15:53
閱讀 2377·2019-08-30 13:59
閱讀 2466·2019-08-29 13:08
閱讀 1175·2019-08-29 12:19
閱讀 3461·2019-08-26 13:41
閱讀 515·2019-08-26 13:24