敏捷軟件開發(fā)第五講開閉原則與里氏替換原則_第1頁
敏捷軟件開發(fā)第五講開閉原則與里氏替換原則_第2頁
敏捷軟件開發(fā)第五講開閉原則與里氏替換原則_第3頁
敏捷軟件開發(fā)第五講開閉原則與里氏替換原則_第4頁
敏捷軟件開發(fā)第五講開閉原則與里氏替換原則_第5頁
已閱讀5頁,還剩29頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第五講:開閉原則與里氏

替換原則敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第1頁!目錄開放——封閉原則(OCP)OCP編程實例OCP原則實施要點Liskov替換原則Liskov原則實施要點總結敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第2頁!開放——封閉原則(OCP)什么是軟件開發(fā)過程中最不穩(wěn)定的因素?——答案是需求!需求在軟件開發(fā)過程中時時刻刻都可能發(fā)生變化。那么,如何靈活應對變化是軟件結構設計中最重要也是最困難的一個問題。好的設計帶來了極大了靈活性,不好的設計則充斥著僵化的臭味。所以我們要遵循——開放封閉原則OCP。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第3頁!開放封閉原則的現(xiàn)實意義開放封閉原則(OCP,OpenClosedPrinciple)是所有面向對象原則的核心。軟件設計本身所追求的目標就是封裝變化、降低耦合。而開放封閉原則正是對這一目標的最直接體現(xiàn)。其他的設計原則,很多時候是為實現(xiàn)這一目標服務的,例如后面將介紹的Liskov替換原則實現(xiàn)最佳的、正確的繼承層次,就能保證不會違反開放封閉原則。OCP核心的思想是:

軟件實體應該是可擴展,而不可修改的。也就是說,對擴展是開放的,而對修改是封閉的。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第4頁!OCP的關鍵在于抽象OCP的關鍵在于抽象抽象技術:abstractclass,Interface抽象預見了可能的所有擴展(閉)由抽象可以隨時導出新的類(開)敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第5頁!設計實現(xiàn)publicclassDoor{privateboolean_isOpen=false;publicbooleanisOpen(){return_isOpen;}publicvoidopen(){_isOpen=true;}publicvoidclose(){_isOpen=false;}}publicclassHand{

publicDoordoor;voiddo(){if(door.isOpen())door.close();elsedoor.open();}}publicclassSmartTest{publicstaticvoidmain(String[]args){HandmyHand=newHand();myHand.door=newDoor();myHand.do();}}敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第6頁!解決新的需求:修改設計publicclassHand{publicDoordoor;publicDrawerdrawer;

voiddo(intitem){switch(item){case1:if(door.isOpen())door.close();elsedoor.open();break; case2: if(drawer.isOpen())drawer.close();elsedrawer.open();break;}}}publicclassSmartTest{publicstaticvoidmain(String[]args){HandmyHand=newHand();myHand.door=newDoor();

myHand.do(1);}}手被改了!主(使用手)程序也被改了!敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第7頁!新的實現(xiàn)publicclassDoor

implementsExcutable{privateboolean_isOpen=false;publicbooleanisOpen(){return_isOpen;}publicvoidopen(){_isOpen=true;}publicvoidclose(){_isOpen=false;}}publicclassHand{publicExcutableitem;

voiddo(){if(item.isOpen())item.close();elseitem.open();}}publicclassDrawer

implementsExcutable{privateboolean_isOpen=false;publicbooleanisOpen(){return_isOpen;}publicvoidopen(){_isOpen=true;}publicvoidclose(){_isOpen=false;}}publicclassSmartTest{publicstaticvoidmain(String[]args){HandmyHand=newHand();myHand.item=newDoor();

myHand.do();}}敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第8頁!OCP原則實施要點預測變化和“貼切的”結構上述的例子其實并不是完全封閉的,如果手增加了新的動作,例如搬運,很多地方還是會有改動變化。那么原來所選定的抽象對于這種變化來說反到成為一種障礙。

一般而言,無論模塊是多么的“封閉”,都會存在一些無法對之封閉的變化。沒有對于所有的情況都貼切的模型。設計人員必須對于他們設計的模塊應該對哪種變化封閉做出選擇。必須先猜測出最有可能發(fā)生的變化種類,然后構造抽象來隔離變化。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第9頁!OCP原則實施要點隔離變化的手段1.“只受一次愚弄”

這意味著在我們最初編寫代碼時,假設變化不會發(fā)生;當變化發(fā)生時,我們就創(chuàng)建抽象來隔離以后發(fā)生的同類變化。2.刺激變化。我們首先編寫測試我們使用很短的迭代周期進行開發(fā)——一個周期為幾天而不是幾周我們在加入基礎結構之前就開發(fā)特性,并且經(jīng)常性的把那些特性展示給涉眾我們首先開發(fā)最重要的特性盡早的、經(jīng)常的發(fā)布軟件敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第10頁!從問題開始!長方形與正方形假如我們有一個類:長方形(Rectangle)我們需要一個新的類,正方形(Square)問:可否直接繼承長方形?沒問題,因為數(shù)學上正方形就是長方形的子類!敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第11頁!設計方案正確嗎?publicstaticvoidresize(Rectangler){while(r.getHeight()<=r.getWidth()){r.setHeight(r.getHeight()+1);}System.out.println(“It’sOK.");}Rectangler1=newRectangle();r1.setHeight(5);r1.setWidth(15);resize(r1);Rectangler2=newSquare();r2.setHeight(5);r2.setWidth(15);resize(r2);使用父類(長方形)時,程序正常運行使用子類(正方形)時,程序陷入死循環(huán)設計出問題了?繼承出問題了?敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第12頁!-13-怎么辦?在可能的情況下,由抽象類(接口)繼承敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第13頁!IS-A關系的思考?鴕鳥是鳥嗎?是鴕鳥有翅膀,鳥也有翅膀鴕鳥有喙,鳥也有喙…但是…鳥.getFlySpeed()鴕鳥.getRunSpeed()有著不同結論:IS-A應當是關于行為的。LSP清晰的指出,OOD中IS-A關系是就行為方式而言的,行為方式是可以進行合理假設的,是客戶程序所依賴的。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第14頁!抽象類與具體類只要有可能,不要從具體類繼承。行為集中的方向是向上的(抽象類)數(shù)據(jù)集中的方向是向下的(具體類)敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第15頁!LSP原則實施要點基于契約設計基于契約設計(DBC:DesignByContract)。使用DBC,類的編寫者能夠顯式的規(guī)定針對該類的契約??蛻舸a的編寫者可以通過該契約獲悉可以依賴的行為方式。契約是通過為每個方法聲明的前置條件(preconditions)和后置條件(postconditions)來指定的。要使一個方法得以執(zhí)行,前置條件必須要為真。執(zhí)行完畢后,該方法要保證后置條件為真。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第16頁!LSP原則實施要點啟發(fā)式規(guī)則1.派生類中的退化函數(shù)在基類中實現(xiàn)了f()方法,在派生類中的函數(shù)f()就是退化的,派生類中的退化函數(shù)并不總表示為違反LSP,但是當存在這種情況時,還是值得注意一下的。2.從派生類中拋出異常在派生類的方法中添加了其基類不會拋出的異常。如果基類的使用者不期望這些異常,那么把它們添加到派生類的方法中就會導致不可替換性。此時要遵循LSP,要么就必須改變使用者的期望,要么派生類就不應該拋出這些異常。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第17頁!總結在許多方面,OCP是面向對象設計的核心所在。遵循這個原則可以帶來面向對象技術所聲稱的巨大好處(也就是:靈活性、可重用性以及可維護性)。然而,并不是說只要使用一種面向對象語言就是遵循了這個原則。對于應用程序中的每個部分都肆意地進行抽象同樣不是一個好主意。正確的做法是,開發(fā)人員應該僅僅對程序中呈現(xiàn)出頻繁變化的那些部分做出抽象。拒絕不成熟的抽象和抽象本身一樣重要。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第18頁!開放——封閉原則(OCP)BertrandMeyer,面向對象技術大師,發(fā)明了Eiffel語言和按契約設計(DesignbyContract)的思想,名著《面向對象軟件構造》的作者,法國工程院院士。目前,他除了擔任Eiffel環(huán)境和工具開發(fā)公司ISE的CTO之外,還是愛因斯坦的母校蘇黎世聯(lián)邦工學院計算機科學系教授,擔任軟件工程項目主席,同時還在澳大利亞Monash大學任教。他于1988年提出了著名的開放——封閉原則(OCP)。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第19頁!OCP特征

軟件實體(類、模塊、函數(shù)等)應該是可擴展的,但是不可修改的。OCP有兩大特征:對于擴展是開放的(Openforextension)模塊的行為可以擴展,當應用的需求改變時,可以對模塊進行擴展,以滿足新的需求。對于更改是封閉的(Closedformodification)對模塊行為擴展時,不必改動模塊的源代碼或二進制代碼。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第20頁!范例:手與門如何在程序中模擬用手去開門和關門?行為:開門(open)關門(close)判斷門的狀態(tài)(isOpened)敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第21頁!新的需求……需要手去開關抽屜,冰箱……?我們只好去修改程序!敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第22頁!符合OCP的設計方案publicinterfaceExcutable{publicbooleanisOpen();publicvoidopen();publicvoidclose();}敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第23頁!新的需求……需要手去開關冰箱……?為冰箱實現(xiàn)Excutable接口不需要修改任何原有的設計和代碼publicclassRefrigerator

implementsExcutable{privateboolean_isOpen=false;publicbooleanisOpen(){return_isOpen;}publicvoidopen(){_isOpen=true;}publicvoidclose(){_isOpen=false;}}敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第24頁!OCP原則實施要點要避免進行多余的抽象遵循OCP的代價也是昂貴的。創(chuàng)建正確的抽象是要花費時間和精力的。同時這些抽象也增加了軟件的復雜性。因此,開閉原則很難被完全實現(xiàn),只能在某些模塊、某種程度上、某個限度內符合OCP的要求。所以可以說,OCP具有理想主義的色彩,是OOD的終極目標。

在項目很緊張的情況下,一般只會對能百分之百預測到的變化經(jīng)行抽象,而且要是那種會經(jīng)常發(fā)生變化的部分才進行抽象。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第25頁!Liskov替換原則(LSP)LSP(TheLiskovSubstitutionPrinciple,Liskov替換原則)“若對于類型S的任一對象o1,均有類型T的對象o2存在,使得在T定義的所有程序P中,用o1替換o2之后,程序的行為不變,則S是T的子類型”如果在任何情況下,子類(或子類型)或實現(xiàn)類與基類都是可以互換的,那么繼承的使用就是合適的。為了達到這一目標,子類不能添加任何父類沒有的附加約束“子類對象必須可以替換父類對象”敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第26頁!開始設計:正方形publicclassRectangle{privateintwidth;privateintheight;publicvoidsetWidth(intw){width=w;}publicintgetWidth(){returnwidth;}publicvoidsetHeight(inth){height=h;}publicintgetHeight(){returnheight;}}publicclassSquare

extendsRectangle{publicvoidsetWidth(intw){super.setWidth(w);super.setHeight(w);}publicvoidsetHeight(inth){super.setWidth(h);super.setHeight(h);}}敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第27頁!違背LSP原則Square類針對height、width添加了Rectangle所沒有的附加的約束違背了LSP原則帶來潛在的設計問題(使用resize方法時,子類出錯?。┟艚蒈浖_發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第28頁!-29-解決方案敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第29頁!IS-A關系的思考(續(xù))對于動物學家只關心鳥的生理特征,對他們來說,鴕鳥就是鳥對于養(yǎng)鳥人關心鳥的行為特征,鴕鳥不是鳥

他們都正確考慮一個特定設計是否恰當時,不能完全孤立地看這個解決方案,應該根據(jù)設計的使用者提出的合理假設來審視。敏捷軟件開發(fā)第五講開閉原則與里氏替換原則共34頁,您現(xiàn)在瀏覽的是第30頁!LSP原則實施要點一個模型,如果孤立的看,并不

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論