<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    軟件是對質(zhì)量的不懈追求

    Bertrand Meyer提出的設(shè)計模式的原則

    【摘 要】 設(shè)計模式的原則就是說模塊應(yīng)對擴展開放,而對修改關(guān)閉。模塊應(yīng)盡量在不修改原(是"原",指原來的代碼)代碼的情況下進行擴展。那么怎么擴展呢?我們看工廠模式"factory pattern":假設(shè)中關(guān)村有一個賣盜版盤和毛片的小子,我們給他設(shè)計一"光盤銷售管理軟件"。

      到底我們?yōu)槭裁匆迷O(shè)計模式呢?這么多設(shè)計模式為什么要這么設(shè)計呢?為什么要提倡"Design Pattern"呢?根本原因是為了代碼復(fù)用,增加可維護性。那么怎么才能實現(xiàn)代碼復(fù)用呢?OO界有前輩的七大原則:"開-閉"原則(Open Closed Principal)、里氏代換原則、合成復(fù)用原則,依賴倒轉(zhuǎn)原則,接口隔離原則,抽象類,迪米特法則。設(shè)計模式就是實現(xiàn)了這些原則,從而達(dá)到了代碼復(fù)用、增加可維護性的目的。

        1、"開-閉"原則

        這些OOD原則的一個基石就是"開-閉原則"(Open-Closed Principle OCP).這個原則最早是由Bertrand Meyer提出,英文的原文是:Software entities should be open for extension,but closed for modification.意思是說,一個軟件實體應(yīng)當(dāng)對擴展開放,對修改關(guān)閉.也就是說,我們在設(shè)計一個模塊的時候,應(yīng)當(dāng)使這個模塊可以在不被修改的前提下被擴展,換句話說就是,應(yīng)當(dāng)可以在不必修改源代碼的情況下改變這個模塊的行為.

          滿足OCP的設(shè)計給系統(tǒng)帶來兩個無可比擬的優(yōu)越性.

          1.通過擴展已有的軟件系統(tǒng),可以提供新的行為,以滿足對軟件的新需求,使變化中的軟件系統(tǒng)有一定的適應(yīng)性和靈活性. 

          2.已有的軟件模塊,特別是最重要的抽象層模塊不能再修改,這就使變化中的軟件系統(tǒng)有一定的穩(wěn)定性和延續(xù)性.

          具有這兩個優(yōu)點的軟件系統(tǒng)是一個高層次上實現(xiàn)了復(fù)用的系統(tǒng),也是一個易于維護的系統(tǒng).那么,我們?nèi)绾尾拍茏龅竭@個原則呢?不能修改而可以擴展,這個看起來是自相矛盾的.其實這個是可以做到的,按面向?qū)ο蟮恼f法,這個就是不允許更改系統(tǒng)的抽象層,而允許擴展的是系統(tǒng)的實現(xiàn)層.

          解決問題的關(guān)鍵在:抽象化.我們讓模塊依賴于一個固定的抽象體,這樣它就是不可以修改的;同時,通過這個抽象體派生,我們就可以擴展此模塊的行為功能.如此,這樣設(shè)計的程序只通過增加代碼來變化而不是通過更改現(xiàn)有代碼來變化,前面提到的修改的副作用就沒有了.

          "開-閉"原則如果從另外一個角度講述,就是所謂的"對可變性封裝原則"(Principle of Encapsulation of Variation, EVP).講的是找到一個系統(tǒng)的可變因素,將之封裝起來.在我們考慮一個系統(tǒng)的時候,我們不要把關(guān)注的焦點放在什么會導(dǎo)致設(shè)計發(fā)生變化上,而是考慮允許什么發(fā)生變化而不讓這一變化導(dǎo)致重新設(shè)計.也就是說,我們要積極的面對變化,積極的包容變化,而不是逃避.

        2、里氏代換原則

    指導(dǎo)我們?nèi)绾稳?gòu)建一個extends(繼承、派生)結(jié)構(gòu)。
    子類與父類的關(guān)系必須是is-A,即,子類必須在任何場合都敢于大聲宣稱自己起碼(至少)是一個父類。比如,假設(shè)某類結(jié)構(gòu),“男人”、“女人”從“人”派生出來,看起來就是滿足里氏代換原則的,因為無論“男人”還是“女人”,在任何場合都是“人”。這個原則大多數(shù)情況下,可以用現(xiàn)實世界中的概念來思考,但軟件世界與顯示世界畢竟有區(qū)別,比如,書中的例子,“正方形是不是矩形”問題。
    此外,很多問題需要利用OO核心思想來靈活考慮,還是書中的例子(我只說大概意思,可能與書中描述存在差異),一個類結(jié)構(gòu),“職工、普通職員、項目經(jīng)理、科長、部長……”,從“員工”類派生出來,從一般概念來看還不錯,職工和部長都是員工嘛,但這里隱含問題,現(xiàn)實世界中,普通職員可能變成項目經(jīng)理,但軟件世界中,普通職員和項目經(jīng)理被規(guī)劃成兩個類了,于是一個普通職員instance是很難變成項目經(jīng)理instance的,這說明我們把顯示世界映射為軟件世界時,出現(xiàn)了問題。更加合理的做法是,把這些職務(wù)(角色)抽象出來,比如叫做“職務(wù)”類(interface/abstract class),所有職務(wù)從其派生,員工類、職務(wù)類是關(guān)聯(lián)關(guān)系,任何一個員工實例都一個職務(wù)實例作為它的屬性,這樣就對了,員工的職務(wù)是可以變化的。實現(xiàn)這個重構(gòu)的依據(jù),是OO中的封裝變化思想,以及從中演化出來的依賴倒換原則、合成/聚合復(fù)用原則。
    但凡涉及到extends結(jié)構(gòu)的設(shè)計模式都符合著里氏代換原則:
    策略模式:一組算法,把他們封裝成對象,使之可以互換(滿足同一接口,即都is-A這個接口)。
    合成模式:Leaf和Composite都is-A Component,于是才可能方便地層層嵌套。
    代理模式:Proxy與RealSubject都is-A父類Subject,于是可以插入代理,完成附加功能。
      

    3、合成復(fù)用原則

      

    合成和聚合都是關(guān)聯(lián)的特殊種類。聚合表示“擁有”關(guān)系或整體與部分的關(guān)系;而合成則是用來表示一種強的多的 “擁有”。在一個合成的關(guān)系里,部分和整體的生命周期是一樣的。一個合成的新的對象完全用又對其他組成部分的支配權(quán)。包括他們的創(chuàng)建和湮滅。組合而成的對象對組成部分的內(nèi)存分配、內(nèi)存釋放有絕對的責(zé)任。 進一步講。一個合成的多重性不能超過1,換言之,一個合成的關(guān)系中,部分對象不能于另一個合成關(guān)系對象共享。
    合成通常理解為:值的聚合。而聚合則是:引用的聚合。
    合成和聚合是將已有的對象納入到新的對象中,使之成為新對象的一部分,因此新的對象可以調(diào)用已由對象的功能。達(dá)到復(fù)用的目的。

    優(yōu)點:

    l    新對象存取成分對象的唯一方法是通過成分對象的接口。

         這種復(fù)用是黑箱復(fù)用,隱藏了成分對象的內(nèi)部細(xì)節(jié)。

         這種復(fù)用支持包裝。

         這種復(fù)用依賴性較小。(耦合度低)

         每一個新類可以將焦點集中在一個任務(wù)上。

         這種復(fù)用可以在運行時動態(tài)進行。新對象可以動態(tài)引用于成分對象類型的子對象。

    缺點就是:

    通過這種復(fù)用建造的系統(tǒng)通常會有較多的對象需要管理。

    “合成聚合復(fù)用可以替代繼承復(fù)用完成任一項功能。”

          4 依賴倒轉(zhuǎn)原則

       很具體地指導(dǎo)我們對抽象類(接口)、實現(xiàn)類的使用。
    依賴于抽象的實體(interface/abstract class),才能夠更具有可插入性(但凡實現(xiàn)既有接口的實現(xiàn)類實例都可以在依賴此接口的地方以此接口實例的角色插入進來),更容易滿足Open- Close原則(抽象的層次不變化、實現(xiàn)的層次由于使用不同的類來封裝不同的變化,于是可以在增加新類作為擴展的同時不需要修改已有實現(xiàn)類)。

         5 接口隔離原則

       含 義:使用多個專門的接口要比使用單一的總接口要好!
    從客戶類角度上看:一個類對另外一個類的依賴性應(yīng)當(dāng)是建立在最小的接口之上。
    接口的劃分直接帶來類型的劃分。
    目標(biāo)就是不向客戶類提供不必要的行為。
         6 抽象類

    抽象類不會有實例,一般作為父類為子類繼承,一般包含這個系的共同屬性和方法。

    注意:好的繼承關(guān)系中,只有葉節(jié)點是具體類,其他節(jié)點應(yīng)該都是抽象類,也就是說具體類

    是不被繼承的。將盡可能多的共同代碼放到抽象類中。

          7 迪米特法則

    用于解開類之間的不必要的耦合。“不要與陌生人說話”。說起來容易,實際操作的時候很可能出現(xiàn)些無所適從的問題,而解開類之間的耦合是比較重要的,目前我們設(shè)計類的時候,增加屬性、增加對其他類的調(diào)用都比較隨意,不太好。
    迪米特法則要求:一個對象應(yīng)當(dāng)對其他對象有盡可能少的了解。幾種其他的表述:只與你直接的朋友通信、不要跟“陌生人”說話(馮遠(yuǎn)征?)
    每個軟件單位對其他單位都具有最少的知識,而且局限于那些與本單位密切相關(guān)的軟件單位。
    狹義迪米特法則-規(guī)定了誰是Friends、誰是Stranger。Friends圈子包括:
    當(dāng)前對象自身(this)、Instance field(如果field是Map、List等容器類型,則容器內(nèi)的對象也是朋友)、當(dāng)前對象創(chuàng)建的對象(調(diào)用其構(gòu)造方法)、當(dāng)前對象方法的參數(shù)對象。
    只跟Friends說話,跟Stranger說的話由Friends轉(zhuǎn)述。
    狹義迪米特法則的弊端:傳遞間接調(diào)用的小方法太多!解決辦法:遵循依賴倒換原則做些折衷處理,讓對象依賴于Stranger的抽象層。雖然沒有完全斷開耦合,至少降低了耦合。

    總結(jié): 軟件系統(tǒng)中,一個模塊設(shè)計的好不好最主要、最重要的標(biāo)志,就是該模塊在多大程度上將自己的內(nèi)部數(shù)據(jù)和其他實現(xiàn)細(xì)節(jié)隱藏起來。一個設(shè)計好的模塊可以將它所有的實現(xiàn)細(xì)節(jié)隱藏起來,很徹底的將提供給外界的API和自己的實現(xiàn)分離開來。這樣一來模塊于模塊之間的通信僅僅通過彼此的API,而不理會模塊內(nèi)部的工作細(xì)節(jié)。這便是:“信息的隱藏”。

    posted on 2008-10-27 13:49 BlakeSu 閱讀(199) 評論(0)  編輯  收藏 所屬分類: 軟件設(shè)計


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 一级毛片免费一级直接观看| 亚洲精品国产首次亮相| 国产一级一毛免费黄片| 亚洲av无码成人精品区| 美女视频黄视大全视频免费的| 在线免费观看一级毛片| 亚洲欧美自偷自拍另类视| 成人午夜性A级毛片免费| 亚洲va久久久久| 成人免费无码大片A毛片抽搐色欲| 亚洲AV成人一区二区三区在线看| 四虎永久在线观看免费网站网址| 亚洲剧场午夜在线观看| 最近高清国语中文在线观看免费| 亚洲中文字幕无码中文字| 日韩免费视频一区| 一区二区在线免费视频| 亚洲国产精品一区二区第一页免| 一级看片免费视频| 久久亚洲一区二区| av无码久久久久不卡免费网站| 亚洲AV成人精品日韩一区18p| 无码免费又爽又高潮喷水的视频| 久久久久亚洲精品男人的天堂| 曰批全过程免费视频在线观看无码| 亚洲人成在线影院| 噼里啪啦电影在线观看免费高清 | 18禁无遮挡无码国产免费网站| 亚洲综合久久成人69| 97无码免费人妻超级碰碰碰碰 | 亚洲中文字幕第一页在线 | 亚洲成a人片在线观看日本| 亚洲欧美日韩中文高清www777| 国产免费卡一卡三卡乱码| 国产日韩在线视频免费播放| 久久久久亚洲AV无码麻豆| 免费av欧美国产在钱| 免费看内射乌克兰女| 亚洲美女aⅴ久久久91| 在线观看国产情趣免费视频 | 免费在线观看h片|