欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
面向對象的設計法則

法則1:優(yōu)先使用(對象)組合,而非(類(lèi))繼承

[ Favor Composition Over Inheritance ]




  • 組合



    1.(對象)組合是一種通過(guò)創(chuàng )建一個(gè)組合了其它對象的對象,從而獲得新功能的復用方法。

    2.將功能委托給所組合的一個(gè)對象,從而獲得新功能。

    3.有些時(shí)候也稱(chēng)之為"聚合"(aggregation)或"包容"(containment),盡管有些作者對這些術(shù)語(yǔ)賦予了專(zhuān)門(mén)的含義

    4.例如:

    a.聚合:一個(gè)對象擁有另一個(gè)對象或對另一個(gè)對象負責(即一個(gè)對象包含另一個(gè)對象或是另一個(gè)對象的一部分),并且聚合對象和其所有者具有相同的生命周期。(譯者注:即所謂的"同生共死"關(guān)系,可參見(jiàn)GOF的Design
    Patterns: Elements of Reusable Object-Oriented Software的引言部分。)

    b.包容:一種特殊類(lèi)型的組合,對于其它對象而言,容器中的被包含對象是不可見(jiàn)的,其它對象僅能通過(guò)容器對象來(lái)訪(fǎng)問(wèn)被包含對象。(Coad)





    5.包含可以通過(guò)以下兩種方式實(shí)現:

    a.根據引用(By reference)

    b.根據值(By value)

    6.C++允許根據值或引用來(lái)實(shí)現包含。

    7.但是在Java中,一切皆為對象的引用!




  • 組合的優(yōu)點(diǎn)和缺點(diǎn)






    1.優(yōu)點(diǎn):

    a.容器類(lèi)僅能通過(guò)被包含對象的接口來(lái)對其進(jìn)行訪(fǎng)問(wèn)。

    b."黑盒"復用,因為被包含對象的內部細節對外是不可見(jiàn)。

    c.對裝性好。

    d.實(shí)現上的相互依賴(lài)性比較小。(譯者注:被包含對象與容器對象之間的依賴(lài)關(guān)系比較少)

    e.每一個(gè)類(lèi)只專(zhuān)注于一項任務(wù)。

    f.通過(guò)獲取指向其它的具有相同類(lèi)型的對象引用,可以在運行期間動(dòng)態(tài)地定義(對象的)組合。




    2.缺點(diǎn):

    a.從而導致系統中的對象過(guò)多。

    b為了能將多個(gè)不同的對象作為組合塊(composition block)來(lái)使用,必須仔細地對接口進(jìn)行定義。




  • 繼承





    1.(類(lèi))繼承是一種通過(guò)擴展一個(gè)已有對象的實(shí)現,從而獲得新功能的復用方法。

    2.泛化類(lèi)(超類(lèi))可以顯式地捕獲那些公共的屬性和方法。

    3.特殊類(lèi)(子類(lèi))則通過(guò)附加屬性和方法來(lái)進(jìn)行實(shí)現的擴展。





  • 繼承的優(yōu)點(diǎn)和缺點(diǎn)





    1.優(yōu)點(diǎn):

    a.容易進(jìn)行新的實(shí)現,因為其大多數可繼承而來(lái)。

    b.易于修改或擴展那些被復用的實(shí)現。

    2.缺點(diǎn):

    a.破壞了封裝性,因為這會(huì )將父類(lèi)的實(shí)現細節暴露給子類(lèi)。

    b. "白盒"復用,因為父類(lèi)的內部細節對于子類(lèi)而言通常是可見(jiàn)的。

    c.當父類(lèi)的實(shí)現更改時(shí),子類(lèi)也不得不會(huì )隨之更改。

    d.從父類(lèi)繼承來(lái)的實(shí)現將不能在運行期間進(jìn)行改變。





  • Coad規則





    僅當下列的所有標準被滿(mǎn)足時(shí),方可使用繼承:

    a.子類(lèi)表達了"是一個(gè)…的特殊類(lèi)型",而非"是一個(gè)由…所扮演的角色"。

    b子類(lèi)的一個(gè)實(shí)例永遠不需要轉化(transmute)為其它類(lèi)的一個(gè)對象。

    c.子類(lèi)是對其父類(lèi)的職責(responsibility)進(jìn)行擴展,而非重寫(xiě)或廢除(nullify)。

    d.子類(lèi)沒(méi)有對那些僅作為一個(gè)工具類(lèi)(utility class)的功能進(jìn)行擴展。

    e.對于一個(gè)位于實(shí)際的問(wèn)題域(Problem Domain)的類(lèi)而言,其子類(lèi)特指一種角色(role),交易(transaction)或設備(device)。





  • 繼承/組合示例1







1."是一個(gè)…的特殊類(lèi)型",而非"是一個(gè)由…所扮演的角色"

-->失敗。乘客是人所扮演的一種角色。代理人亦然。

2.永遠不需要轉化

-->失敗。隨著(zhù)時(shí)間的發(fā)展,一個(gè)Person的子類(lèi)實(shí)例可能會(huì )從Passenger轉變成Agent,再到Agent Passenger。

3.擴展,而非重寫(xiě)和廢除

-->通過(guò)。

4.不要擴展一個(gè)工具類(lèi)

-->通過(guò)。

5.在問(wèn)題域內,特指一種角色,交易或設備

-->失敗。Person不是一種角色,交易或設備。






繼承并非適用于此處!


使用組合進(jìn)行挽救!





  • 繼承/組合示例2







1."是一個(gè)…的特殊類(lèi)型",而非"是一個(gè)由…所扮演的角色"

-->通過(guò)。乘客和代理人都是特殊類(lèi)型的人所扮演的角色。

2.永遠不需要轉化

-->通過(guò)。一個(gè)Passenger對象將保持不變;Agent對象亦然。

3.擴展,而非重寫(xiě)和廢除

-->通過(guò)。

4.不要擴展一個(gè)工具類(lèi)

-->通過(guò)。

5.在問(wèn)題域內,特指一種角色,交易或設備

-->通過(guò)。PersonRole是一種類(lèi)型的角色。




繼承適用于此處!




  • 繼承/組合示例3







1."是一個(gè)…的特殊類(lèi)型",而非"是一個(gè)由…所扮演的角色"

-->通過(guò)。預訂和購買(mǎi)都是一種特殊類(lèi)型的交易。

2.永遠不需要轉化

-->通過(guò)。一個(gè)Reservation對象將保持不變;Purchase對象亦然。

3.擴展,而非重寫(xiě)和廢除

-->通過(guò)。

4.不要擴展一個(gè)工具類(lèi)

-->通過(guò)。

5.在問(wèn)題域內,特指一種角色,交易或設備

-->通過(guò)。是一種交易。




繼承適用于此處!




  • 繼承/組合示例4







1."是一個(gè)…的特殊類(lèi)型",而非"是一個(gè)由…所扮演的角色"

-->失敗。預訂不是一種特殊類(lèi)型的observable。

2.永遠不需要轉化

-->通過(guò)。一個(gè)Reservation對象將保持不變。

3.擴展,而非重寫(xiě)和廢除

-->通過(guò)。

4.不要擴展一個(gè)工具類(lèi)

-->失敗。Observable就是一個(gè)工具類(lèi)。

5.在問(wèn)題域內,特指一種角色,交易或設備

-->不適用。Observable是一個(gè)工具類(lèi),并非一個(gè)問(wèn)題域的類(lèi)。。




繼承并非適用于此處!




  • 繼承/組合總結





    1.組合與繼承都是重要的重用方法

    2.在OO開(kāi)發(fā)的早期,繼承被過(guò)度地使用

    3.隨著(zhù)時(shí)間的發(fā)展,我們發(fā)現優(yōu)先使用組合可以獲得重用性與簡(jiǎn)單性更佳的設計

    4.當然可以通過(guò)繼承,以擴充(enlarge)可用的組合類(lèi)集(the set of composable classes)。

    5.因此組合與繼承可以一起工作

    6.但是我們的基本法則是:

    優(yōu)先使用對象組合,而非(類(lèi))繼承

    [ Favor Composition Over Inheritance ]

    法則2:針對接口編程,而非(接口的)實(shí)現

    [ Program To An Interface, Not An Implementation ]





    • 接口



      1.接口是一個(gè)對象在對其它的對象進(jìn)行調用時(shí)所知道的方法集合。

      2.一個(gè)對象可以有多個(gè)接口(實(shí)際上,接口是對象所有方法的一個(gè)子集)

      3.類(lèi)型是對象的一個(gè)特定的接口。

      4.不同的對象可以具有相同的類(lèi)型,而且一個(gè)對象可以具有多個(gè)不同的類(lèi)型。

      5.一個(gè)對象僅能通過(guò)其接口才會(huì )被其它對象所了解。

      6.某種意義上,接口是以一種非常局限的方式,將"是一種…"表達為"一種支持該接口的…"。

      7.接口是實(shí)現插件化(pluggability)的關(guān)鍵





    • 實(shí)現繼承和接口繼承



      1.實(shí)現繼承(類(lèi)繼承):一個(gè)對象的實(shí)現是根據另一個(gè)對象的實(shí)現來(lái)定義的。

      2.接口繼承(子類(lèi)型化):描述了一個(gè)對象可在什么時(shí)候被用來(lái)替代另一個(gè)對象。

      3.C++的繼承機制既指類(lèi)繼承,又指接口繼承。

      4.C++通過(guò)繼承純虛類(lèi)來(lái)實(shí)現接口繼承。

      5.Java對接口繼承具有單獨的語(yǔ)言構造方式-Java接口。

      6.Java接口構造方式更加易于表達和實(shí)現那些專(zhuān)注于對象接口的設計。





    • 接口的好處



      1.優(yōu)點(diǎn)

      a.Client不必知道其使用對象的具體所屬類(lèi)。

      b.一個(gè)對象可以很容易地被(實(shí)現了相同接口的)的另一個(gè)對象所替換。

      c.對象間的連接不必硬綁定(hardwire)到一個(gè)具體類(lèi)的對象上,因此增加了靈活性。

      e.松散藕合(loosens coupling)。

      f.增加了重用的可能性。

      e.提高了(對象)組合的機率,因為被包含對象可以是任何實(shí)現了一個(gè)指定接口的類(lèi)。

      2.缺點(diǎn):

      a.設計的復雜性略有增加

      (譯者注:接口表示"…像…"(LikeA)的關(guān)系,繼承表示"…是…"(IsA)的關(guān)系,組合表示"…有…"(HasA)的關(guān)系。)





    • 接口實(shí)例








    該方法是指其它的一些類(lèi)可以進(jìn)行交通工具的駕駛,而不必關(guān)心其實(shí)際上是(汽車(chē),輪船,潛艇或是其它任何實(shí)現了IManeuverabre的對象)。


    法則3:開(kāi)放-封閉法則(OCP)

    軟件組成實(shí)體應該是可擴展的,但是不可修改的。

    [ Software Entities Should Be Open For Extension, Yet Closed For Modification
    ]




    • 開(kāi)放-封閉法則





      1.開(kāi)放-封閉法則認為我們應該試圖去設計出永遠也不需要改變的模塊。

      2我們可以添加新代碼來(lái)擴展系統的行為。我們不能對已有的代碼進(jìn)行修改。

      3.符合OCP的模塊需滿(mǎn)足兩個(gè)標準:

      4.可擴展,即"對擴展是開(kāi)放的"(Open For Extension)-模塊的行為可以被擴展,以需要滿(mǎn)足新的需求。

      5.不可更改,即"對更改是封閉的"(Closed for Modification)-模塊的源代碼是不允許進(jìn)行改動(dòng)的。

      6.我們能如何去做呢?

      a.抽象(Abstraction)

      b.多態(tài)(Polymorphism)

      c.繼承(Inheritance)

      d.接口(Interface)


      7. 一個(gè)軟件系統的所有模塊不可能都滿(mǎn)足OCP,但是我們應該努力最小化這些不滿(mǎn)足OCP的模塊數量。

      8.開(kāi)放-封閉法則是OO設計的真正核心。

      9.符合該法則便意味著(zhù)最高等級的復用性(reusability)和可維護性(maintainability)。





    • OCP示例



      1. 考慮下面某類(lèi)的方法:





      2.以上函數的工作是在制訂的部件數組中計算各個(gè)部件價(jià)格的總和。

      3.若Part是一個(gè)基類(lèi)或接口且使用了多態(tài),則該類(lèi)可很容易地來(lái)適應新類(lèi)型的部件,而不必對其進(jìn)行修改。

      4.其將符合OCP


      5. 但是在計算總價(jià)格時(shí),若財務(wù)部頒布主板和內存應使用額外費用,則將如何去做。

      6.下列的代碼是如何來(lái)做的呢?





      7.這符合OCP嗎?

      8.當每次財務(wù)部提出新的計價(jià)策略,我們都不得不要修改totalPrice()方法!這并非"對更改是封閉的"。顯然,策略的變更便意味著(zhù)我們不得不要在一些地方修改代碼的,因此我們該如何去做呢?

      9.為了使用我們第一個(gè)版本的totalPrice(),我們可以將計價(jià)策略合并到Part的getPrice()方法中。


      10.這里是Part和ConcretePart類(lèi)的示例:



      11. 但是現在每當計價(jià)策略發(fā)生改變,我們就必須修改Part的每個(gè)子類(lèi)!

      12.一個(gè)更好的思路是采用一個(gè)PricePolicy類(lèi),通過(guò)對其進(jìn)行繼承以提供不同的計價(jià)策略:




      13.看起來(lái)我們所做的就是將問(wèn)題推遲到另一個(gè)類(lèi)中。但是使用該解決方案,我們可通過(guò)改變Part對象,在運行期間動(dòng)態(tài)地來(lái)設定計價(jià)的策略。

      14.另一個(gè)解決方案是使每個(gè)ConcretePart從數據庫或屬性文件中獲取其當前的價(jià)格。





    • 單選法則



      單選法則(the Single Choice Principle)是OCP的一個(gè)推論。

      無(wú)論在什么時(shí)候,一個(gè)軟件系統必須支持一組備選項,理想情況下,在系統中只能有一個(gè)類(lèi)能夠知道整個(gè)的備選項集合。


      法則4:Liskov替換法則(LSP)

      使用指向基類(lèi)(超類(lèi))的引用的函數,必須能夠在不知道具體派生類(lèi)(子類(lèi))對象類(lèi)型的情況下使用它們。

      [ Function Thar Use Referennces To Base(Super) Classes Must Be Able To Use Objects
      Of Derived(Sub) Classes Without Knowing It ]




      • Liskov替換法則





        1.顯而易見(jiàn),Liskov替換法則(LSP)是根據我所熟知的"多態(tài)"而得出的。

        2.例如:



        方法drawShape應該可與Sharp超類(lèi)的任何子類(lèi)一起工作(或者,若Sharp為Java接口,則該方法可與任何實(shí)現了Sharp接口的類(lèi)一起工作)

        但是當我們在實(shí)現子類(lèi)時(shí)必須要謹慎對待,以確保我們不會(huì )無(wú)意中違背了LSP。





        3.若一個(gè)函數未能滿(mǎn)足LSP,那么可能是因為它顯式地引用了超類(lèi)的一些或所有子類(lèi)。這樣的函數也違背了OCP,因為當我們創(chuàng )建一個(gè)新的子類(lèi)時(shí),會(huì )不得不進(jìn)行代碼的修改。




      • LSP示例



        1. 考慮下面Rectangle類(lèi):



        2.現在,Square類(lèi)會(huì )如何呢?顯然,一個(gè)正方形是一個(gè)四邊形,因此Square類(lèi)應該從Rectangle類(lèi)派生而來(lái),對否?讓我們看一看!

        3.觀(guān)察可得:

        a.正方形不需要將高和寬都作為屬性,但是總之它將繼承自Rectangle。因此,每一個(gè)Square對象會(huì )浪費一點(diǎn)內存,但這并不是一個(gè)主要問(wèn)題。

        b.繼承而來(lái)的setWidth()和setHeight()方法對于Square而言并非真正地適合,因為一個(gè)正方形的高和寬是相同。因此我們將需要重寫(xiě)setWidth()和setHeight()方法。不得不重寫(xiě)這些簡(jiǎn)單的方法有可能是一種不恰當的繼承使用方式。


        3.Square類(lèi)如下:










      4. 看起來(lái)都還不錯。但是讓我們檢驗一下!








      5. 測試程序輸出:







      6.看上去好像我們違背了LSP!


      7.這里的問(wèn)題出在哪里呢?編寫(xiě)testLsp()方法的程序員做了一個(gè)合理的假設,即改變Rectangle的寬而保持它的高不變。

      8.在將一個(gè)Square對象傳遞給這樣一個(gè)方法時(shí)產(chǎn)生了問(wèn)題,顯然是違背了LSP

      9.Square和Rectangle類(lèi)是相互一致和合法的。盡管程序員對基類(lèi)作了合理的假設,但其所編寫(xiě)的方法仍然會(huì )導致設計模型的失敗。

      10.不能孤立地去看待解決方案,必須根據設計用戶(hù)所做的合理假設來(lái)看待它們。


      11. 一個(gè)數學(xué)意義上的正方形可能是一個(gè)四邊形,但是一個(gè)Square對象不是一個(gè)Rectangle對象,因為一個(gè)Square對象的行為與一個(gè)Rectangle對象的行為是不一致的!

      12.從行為上來(lái)說(shuō),一個(gè)Square不是一個(gè)Rectangle!一個(gè)Square對象與一個(gè)Rectangle對象之間不具有多態(tài)的特征。






      • 總結





        1.Liskov替換法則(LSP)清楚地表明了ISA關(guān)系全部都是與行為有關(guān)的。

        2.為了保持LSP(并與開(kāi)放-封閉法則一起),所有子類(lèi)必須符合使用基類(lèi)的client所期望的行為。

        3.一個(gè)子類(lèi)型不得具有比基類(lèi)型(base type)更多的限制,可能這對于基類(lèi)型來(lái)說(shuō)是合法的,但是可能會(huì )因為違背子類(lèi)型的其中一個(gè)額外限制,從而違背了LSP!

        4.LSP保證一個(gè)子類(lèi)總是能夠被用在其基類(lèi)可以出現的地方!

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
一些面向對象的設計法則
敏捷開(kāi)發(fā)之原則 五大原則 SRP OCP LSP DIP ISP
程序員該有的藝術(shù)氣質(zhì)—SOLID原則
Java程序員應該了解的10個(gè)面向對象設計原則
Java程序員應當知道的10個(gè)面向對象設計原則
設計六大原則總結
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久