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

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

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

    ivaneeo's blog

    自由的力量,自由的生活。

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

    #

    客戶直接調用其server object(服務對象)的delegate class。

    在server端(某個class)建立客戶所需的所有函數,用以隱藏委托關系(delegation)。

    Hide_Delegate.png
    posted @ 2005-08-31 11:09 ivaneeo 閱讀(153) | 評論 (0)編輯 收藏

    先前(上個重構項)我從TelephoneNumber提煉出另一個class,現在我要將它inlining塞回到Person去。一開始這兩個classes是分離的:
    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;

    首先我在Person中聲明TelephoneNumber的所有[可見](public)函數:
    class Person...
        String getAreaCode() {
           return _officeTelephone.getAreaCode();
        }
        void setAreaCode(String arg) {
           _officeTelephone.setAreaCode(arg);
        }
        String getNumber() {
           return
    _officeTelephone.getNumber();
        }
        void setNumber(String arg) {
          
    _officeTelephone.setNumber(arg);
        }


    現在,我要找出TelephoneNumber的所有用戶,讓它們轉而使用Person接口。于是下列代碼:
        Person martin = new Person();
        martin.getOfficeTelephone().setAreaCode("781");
    就變成了:
        Person martin = new Person();
        martin.setAreaCode("781");
    現在,我可以持續使用Move Method(142)和Move Field(146),直到TelephoneNumber不復存在。
    posted @ 2005-08-31 10:57 ivaneeo 閱讀(201) | 評論 (0)編輯 收藏

    作法(Mechanics)
      • 在absorbing class(合并端的那個class)身上聲明source class的public協議,并將其中所有函數委托(delegate)至source class。
          • ==》如果[以一個獨立接口表示source class函數]更合適的話,就應該在inlining之前先使用Extract Interface(341)。
      • 修改所有source class引用點,改而引用absorbing class。
          • ==》將source class聲明為private,以斬斷package之外的所有引用可能。
          • 同時并修改source class的名稱,這便可使編譯器幫助你捕捉到所有對于source class的“dangling references”(虛懸引用點)。
      • 編譯,測試。
      • 運用Move Method(142)和Move Field(146),將source class的特性全部搬移到absorbing class。
      • 為source class舉行一個簡單的葬禮。
    posted @ 2005-08-31 10:42 ivaneeo 閱讀(137) | 評論 (0)編輯 收藏

    動機(Motivation)
    Inline Class(154)正好與Extract Class(149)相反。如果一個class不再承擔足夠責任、不再有單獨存在的理由(這通常是因為此前的重構動作移走了這個class的責任),我就會挑選這一[萎縮class]的最頻繁用戶(也是個class),以Inline Class(154)手法將[萎縮class]塞進去。
    posted @ 2005-08-31 10:02 ivaneeo 閱讀(143) | 評論 (0)編輯 收藏

    你的某個class沒有做太多事情(沒有承擔足夠責任)。

    將class的所有特性搬移到另一個class中,然后移除原class。

    Inline_Class.png
    posted @ 2005-08-30 16:44 ivaneeo 閱讀(179) | 評論 (0)編輯 收藏

    讓我們從一個簡單的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(146)移動一個值域:
    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(142)將相關函數移動到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(179)。這種情況下,Person應該是TelephoneNumber的訪問點。
    2.不許任何人[不通過Person對象就修改TelephoneNumber對象]。為了達到目的,我可以將TelephoneNumber設為不可修改的(immutable),或為它提供一個不可修改的接口(immutable interface)。
    3.另一個辦法是:先復制一個TelephoneNumber對象,然后將復制得到的新對象傳遞給用戶。但這可能會造成一定程度的迷惑,因為人們會認為他們可以修改TelephoneNumber對象值。此外,如果同一個TelephoneNumber對象被傳遞給多個用戶,也可能在用戶之間造成別名(aliasing)問題。

    Extract Class(149)是改善并發(concurrent)程序的一種常用技術,因為它使你可以提煉后的兩個classes分別加鎖(locks)。
    posted @ 2005-08-30 16:33 ivaneeo 閱讀(209) | 評論 (0)編輯 收藏

    作法(Mechanics)
      • 決定如何分解class所負責任。
      • 建立一個新class,用以表現從舊class中分離出來的責任。
          • ==》如果舊class剩下的責任與舊class名稱不符,為舊class易名。
      • 建立[從舊class訪問新class]的連接關系(link)。
          • ==》也許你有可能需要一個雙向連接。但是在真正需要它之前,不要建立[從新class同往舊class]的連接。
      • 對于你想搬移的每一個值域,運用Move Field(146)搬移之。
      • 每次搬移后,編譯、測試。
      • 使用Move Method(142)將必要函數搬移到新class。先搬移較低層函數(也就是[就其他函數調用]多于[調用其他函數]者),再搬移較高層函數。
      • 每次搬移之后,編譯、測試。
      • 檢查,精簡每個class的接口。
          • ==》如果你建立起雙向連接,檢查是否可以將它改為單向連接。
      • 決定是否讓新class暴光。如果你的的確需要暴光它,決定讓它成為reference object(引用型對象)或immutable value object(不可變之[實值型對象])。
    posted @ 2005-08-30 15:46 ivaneeo 閱讀(165) | 評論 (0)編輯 收藏

    動機(Motivation)
    如果某些數據和某些函數總是一起出現,如果某些數據經常同時變化甚至彼此相依,這就表示你應該將它們分離出去。

    另一個往往在開發后期出現的信號是class的[subtyped方式]。如果你發現subtyping只影響class的部分特性,或如果你發現某些特 性[需要以此方式subtyped],某些特性[需要以彼此方式subtyped],這就是意味你需要分解原來的class。
    posted @ 2005-08-30 15:33 ivaneeo 閱讀(170) | 評論 (0)編輯 收藏

    某個class做了應該由兩個classes做的事。

    建立一個新class,將相關的值域和函數從舊class搬移到新class。

    Extract_Class.png
    posted @ 2005-08-30 15:23 ivaneeo 閱讀(165) | 評論 (0)編輯 收藏

    如果有很多函數已經使用了_interestRate field,我應該先運用Self Encapsulate Field(171):
    class Account...
        private AccountType _type;
        private double _interestRate;
        double interestForAmount_days(double amount, int days) {
           return getInterestRate() * amount * days / 365;
        }
        private void setInterestRate(double arg) {

           _interestRate = arg;
        }
        private double getInterestRate() {
           return _interestRate;
        }

    這樣,在搬移field之后,我就只需要修改訪問函數就行了:

        double interestForAmount_days(double amount, int days) {
           return getInterestRate() * amount * days / 365;
        }
        private void setInterestRate(double arg) {

           _type.setInterestRate(arg);
        }
        private double getInterestRate() {
           return _type.getInterestRate();
        }

    如果以后有必要,我可以修改訪問函數(accessors)的用戶,讓它們使用新對象。Self Encapsulate Field(171)使我得以保持小步前進。如果我需要對class做許多處理,保持小步前進是有幫助的。特別值得一提的是:首先使用
    Self Encapsulate Field(171)使我得以更輕松使用Move Method(142)將函數搬移到target class中。如果待移函數引用了field的訪問函數(accessors),那么那些引用點是無須修改的。

    posted @ 2005-08-30 14:59 ivaneeo 閱讀(128) | 評論 (0)編輯 收藏

    僅列出標題
    共67頁: First 上一頁 44 45 46 47 48 49 50 51 52 下一頁 Last 
    主站蜘蛛池模板: 一二三四视频在线观看中文版免费| 大桥未久亚洲无av码在线| 亚洲日韩欧洲无码av夜夜摸| xvideos亚洲永久网址| 特级毛片全部免费播放a一级| 亚洲国产精品嫩草影院| 亚洲AV无码专区在线电影成人 | 精品国产人成亚洲区| 中文字幕av无码无卡免费 | 国产一区二区三区亚洲综合| 亚洲av无码兔费综合| 免费无码又爽又黄又刺激网站 | 亚洲狠狠成人综合网| 亚洲国产综合91精品麻豆| 亚洲AV日韩AV鸥美在线观看| 亚洲精品私拍国产福利在线| 亚洲视频免费观看| 亚洲中文无码a∨在线观看| 亚洲另类激情综合偷自拍图| 四虎国产精品免费视| 亚洲日本va午夜中文字幕久久| 国产亚洲人成网站在线观看| 精品久久久久久亚洲| 德国女人一级毛片免费| 亚洲毛片在线免费观看| 久久WWW免费人成人片| 国产免费看插插插视频| 亚洲中文字幕视频国产| 久久综合日韩亚洲精品色| 亚洲综合图片小说区热久久| 亚洲性无码一区二区三区| 国产亚洲精品2021自在线| 99久久99这里只有免费的精品| 日韩精品极品视频在线观看免费 | 亚洲免费二区三区| 亚洲AV无码一区二区乱子仑| 精品乱子伦一区二区三区高清免费播放| 美国免费高清一级毛片| AAA日本高清在线播放免费观看| 国产视频精品免费视频| 1000部拍拍拍18勿入免费视频下载 |