<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### Extract Class(提煉類) 某個class做了應該由兩個classes做的事。 建立一個新class,將相關的值域和函數從舊class搬移到新class。 ![](https://box.kancloud.cn/2016-08-15_57b1b56c3d0d7.gif) **動機(Motivation)** 你也許聽過類似這樣的教誨:一個class應該是一個清楚的抽象(abstract),處理一些明確的責任。但是在實際工作中,class會不斷成長擴展。你會在這兒加入一些功能,在那兒加入一些數據。給某個class添加一項新責任時,你會覺得不值得為這項責任分離出一個單獨的class。于是,隨著責任不斷増加,這個class會變得過份復雜。很快,你的class就會變成一團亂麻。 這樣的class往往含有大量函數和數據。這樣的class往往太大而不易理解。此時你需要考慮哪些部分可以分離出去,并將它們分離到一個單獨的class中。如果某些數據和某些函數總是一起出現,如果某些數據經常同時變化甚至彼此相依,這就表示你應該將它們分離出去。一個有用的測試就是問你自己,如果你搬移了某些值域和函數,會發生什么事?其他值域和函數是否因此變得無意義? 另一個往往在開發后期出現的信號是class的「subtyped方式」。如果你發現subtyping只影響class的部分特性,或如果你發現某些特性「需要以此方式subtyped」,某些特性「需要以彼方式subtyped」,這就意味你需要分解原來的class。 **作法(Mechanics)** - 決定如何分解c;ass所負責任。 - 建立一個新class,用以表現從舊class中分離出來的責任。 - 如果舊class剩下的責任與舊class名稱不符,為舊class易名。 - 建立「從舊class訪問新class」的連接關系(link)。 - 也許你有可能需要一個雙向連接。但是在真正需要它之前,不要建立 「從新class通往舊class」的連接。 - 對于你想搬移的每一個值域,運用Move Field 搬移之。 - 每次搬移后,編譯、測試。 - 使用Move Method 將必要函數搬移到新class。先搬移較低層函數(也就是「被其他函數調用」多于「調用其他函數」者),再搬移較高層函數。 - 每次搬移之后,編譯、測試。 - 檢查,精簡每個class的接口。 - 如果你建立起雙向連接,檢查是否可以將它改為單向連接。 - 決定是否讓新class曝光。如果你的確需要曝光它,決定讓它成為reference object (引用型對象〕或immutable value object(不可變之「實值型對象」)。 **范例(Examples)** 讓我們從一個簡單的Person class開始: ~~~ class Person... public String getName() { return _name; } public String getTelephoneNumber() { return ("(" + _officeAreaCode + ") " + _officeNumber); } String getOfficeAreaCode() { return _officeAreaCode; } void setOfficeAreaCode(String arg) { _officeAreaCode = arg; } String getOfficeNumber() { return _officeNumber; } void setOfficeNumber(String arg) { _officeNumber = arg; } private String _name; private String _officeAreaCode; private String _officeNumber; ~~~ 在這個例子中,我可以將「與電話號碼相關」的行為分離到一個獨立class中。首 先我耍定義一個TelephoneNumber class來表示「電話號碼」這個概念: ~~~ class TelephoneNumber { } ~~~ 易如反掌!然后,我要建立從Person到TelephoneNumber的連接: ~~~ class Person private TelephoneNumber _officeTelephone = new TelephoneNumber(); ~~~ 現在,我運用Move Field 移動一個值域: ~~~ class TelephoneNumber { String getAreaCode() { return _areaCode; } void setAreaCode(String arg) { _areaCode = arg; } private String _areaCode; } class Person... public String getTelephoneNumber() { return ("(" + getOfficeAreaCode() + ") " + _officeNumber); } String getOfficeAreaCode() { return _officeTelephone.getAreaCode(); } void setOfficeAreaCode(String arg) { _officeTelephone.setAreaCode(arg); } ~~~ 然后我可以移動其他值域,并運用Move Method 將相關函數移動到TelephoneNumber class中: ~~~ class Person... public String getName() { return _name; } public String getTelephoneNumber(){ return _officeTelephone.getTelephoneNumber(); } TelephoneNumber getOfficeTelephone() { return _officeTelephone; } private String _name; private TelephoneNumber _officeTelephone = new TelephoneNumber(); class TelephoneNumber... public String getTelephoneNumber() { return ("(" + _areaCode + ") " + _number); } String getAreaCode() { return _areaCode; } void setAreaCode(String arg) { _areaCode = arg; } String getNumber() { return _number; } void setNumber(String arg) { _number = arg; } private String _number; private String _areaCode; ~~~ 下一步要做的決定是:要不要對客戶揭示這個新口class?我可以將Person中「與電 話號碼相關」的函數委托(delegating)至TelephoneNumber,從而完全隱藏這個新class;也可以直接將它對用戶曝光。我還可以將它暴露給部分用戶(位于同一個package中的用戶),而不暴露給其他用戶。 如果我選擇暴露新class,我就需要考慮別名(aliasing)帶來的危險。如果我暴露了TelephoneNumber ,而有個用戶修改了對象中的_areaCode值域值,我又怎么能知道呢?而且,做出修改的可能不是直接用戶,而是用戶的用戶的用戶。 面對這個問題,我有下列數種選擇: 1. 允許任何對象修改TelephoneNumber 對象的任何部分。這就使得TelephoneNumber 對象成為引用對象(reference object),于是我應該考慮使用 Change Value to Reference。這種情況下,Person應該是TelephoneNumber的訪問點。 1. 不許任何人「不通過Person對象就修改TelephoneNumber 對象」。為了達到目的,我可以將TelephoneNumber「設為不可修改的(immutable),或為它提供一個不可修改的接口(immutable interface)。 1. 另一個辦法是:先復制一個TelephoneNumber 對象,然后將復制得到的新對象傳遞給用戶。但這可能會造成一定程度的迷惑,因為人們會認為他們可以修改TelephoneNumber對象值。此外,如果同一個TelephoneNumber 對象 被傳遞給多個用戶,也可能在用戶之間造成別名(aliasing)問題。 Extract Class 是改善并發(concurrent)程序的一種常用技術,因為它使你可以為提煉后的兩個classes分別加鎖(locks)。如果你不需要同時鎖定兩個對象, 你就不必這樣做。這方面的更多信息請看Lea[Lea], 3.3節。 這里也存在危險性。如果需要確保兩個對象被同時鎖定,你就面臨事務(transaction)問題,需要使用其他類型的共享鎖〔shared locks〕。正如Lea[Lea] 8.1節所討論, 這是一個復雜領域,比起一般情況需要更繁重的機制。事務(transaction)很有實用性,但是編寫事務管理程序(transaction manager)則超出了大多數程序員的職責范圍。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看