ivaneeo's blog

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

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

          #

          范例(Examples)
          class IntRange {
              private int _low, _high;
             
              boolean includes(int arg) {
                 return arg >= _low && arg <= _high;
              }

              void grow(int factor) {
                 _high = _high * factor;
              }

              IntRange(int low, int high) {
                 _low = low;
                 _high = high;
              }
          為了封裝_low和_high這兩個值域,我先定義[取值/設值函數](如果此前沒有定義的話),并使用它們:
          class IntRange {
              private int _low, _high;
             
              boolean includes(int arg) {
                 return arg >= _low && arg <= _high;
              }

              void grow(int factor) {
                 _high = _high * factor;
              }

              int getLow() {
                 return _low;
              }

              int getHigh() {
                 return _high;
              }

              void setLow(int arg) {
                 _low = arg;
              }

              void setHigh(int arg) {
                 _high = arg;
              }
          使用本項重構時,一般說來,設值函數被認為應該在[對象創建后]才使用,所以初始化過程中的行為有可能與設值函數的行為不同。這種情況下,我也許在構造函數中直接訪問值域,要不就是建立另一個獨立的初始化函數:
          IntRange(int low, int high) {
              initialize(low, high);
          }
          private void initialize(int low, int high) {
              _low = low;
              _high = high;
          }
          一旦你擁有一個subclass,上述所有動作的價值就體現出來了。如下所示:
          class CappedRange extends IntRange {
              CappedRange(int low, int high, int cap) {
                 super(low, high);
                 _cap = cap;
              }

              private int _cap;

              int getCap() {
                 return _cap;
              }
              
              int getHigh() {
                 return Math.min(super.getHigh(), getCap());
              }
          }
          現在,我可以CappedRange class中覆寫getHigh(),從而加入對cap的考慮,而不必修改IntRange class的任何行為。
          posted @ 2005-08-31 15:57 ivaneeo 閱讀(221) | 評論 (0)編輯 收藏

          作法(Mechanics)
            • 為[待封裝值域]建立取值/設值函數(getting/setting methods)。
            • 找出該值域的所有引用點,將它們全部替換為[對于取值/設值函數的調用]。
                • ==》如果引用點是[讀值]值域值,就將它替換為[調用取值函數];如果引用點是[設定]值域值,就將它替換為[調用設值函數]。
                • ==》你可以暫時為設值域改名,讓編譯器幫助你查找引用點。
            • 將該值域聲明為private。
            • 復查,確保找出所有引用點。
            • 編譯,測試。
          posted @ 2005-08-31 15:51 ivaneeo 閱讀(200) | 評論 (0)編輯 收藏

          動機(Motivation)
          如果你想訪問superclass中的一個值域,卻又想在subclass中將[對這個變量的訪問]改為一個計算后的值,這就是最該使用Self Encapsulate Field(171)的時候。[值域自我封裝]只是第一步。完成自我封裝之后,你可以在subclass中根據自己的需要隨意覆寫取值/設值函數(getting/setting methods)。
          posted @ 2005-08-31 15:44 ivaneeo 閱讀(181) | 評論 (0)編輯 收藏

          你直接訪問一個值域(field),但與值域之間的耦合關系逐漸變得笨拙。

          為這個值域建立取值/設值函數(getting/setting methods),并且只以這些函數來訪問值域。
          private int _low, _high;
          boolean includes(int arg) {
              return arg >= _low && arg <= _high;
          }
                                126.gif
          private int _low, _high;
          boolean includes(int arg) {
              return arg >= getLow() && arg <= getHigh();
          }
          int getLow() {return _low;}
          int getHigh() {return _high;}
          posted @ 2005-08-31 15:36 ivaneeo 閱讀(208) | 評論 (0)編輯 收藏

          首先聲明一個wrapping class:
              class MfDateWrap {
                 private Date _original;
              }
          使用wrapping方案時,我對構造函數的設定與先前有所不同。現在的構造函數將只是執行一個單純的委托動作(delegation):
              public MfDateWrap(String dateString) {
                 _original = new Date(dateString);
              }
          而轉型構造函數則只是對其instance變量賦值而已:
              public int getYear() {
                 return _original.getYear();
              }
              public boolean equals(MfDateWrap arg) {
                 return (toDate().equals(arg.toDate());
              }
          完成這項工作之后,我就可以后使用Move Method(142)將日期相關行為搬移到新class中。于是以下代碼:
              client class...
                 private static Date nextDay(Date arg) {
                    return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1);
                 }
          經過搬移之后,就成了:
              class MfDate...
                 Date nextDay() {
                    return new Date(getYear(), getMonth(), getDate() + 1);
                 }
          posted @ 2005-08-31 15:27 ivaneeo 閱讀(170) | 評論 (0)編輯 收藏

          首先,我要建立一個新的MfDateSub class來表示[日期],并使其成為Date的subclass:
              class MfDateSub extends Date
          然后,我需要處理Date和我的extension class之間的不同處。MfDateSub構造函數需要委托(delegating)給Date構造函數:
              public MfDateSub(String dateString) {
                 super(dateString);
              }
          現在,我需要加入一個轉型構造函數,其參數是一個隸屬原類的對象:
              public MfDateSub(Date arg){
                 super(arg.getTime());
              }
          現在,我可以在extension class中添加新特性,并使用Move Method(142)將所有外加函數(foreign method)搬移到extension class。于是,下面的代碼:
              client class...
                 private static Date nextDay(Date arg) {
                    return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1);
                 }
          經過搬移之后,就成了:
              class MfDate...
                 Date nextDay() {
                    return new Date(getYear(), getMonth(), getDate() + 1);
                 }
          posted @ 2005-08-31 15:14 ivaneeo 閱讀(199) | 評論 (0)編輯 收藏

          我將以Java1.0.1的Date class為例。Java 1.1已經提供了我想要的功能,但是在它到來之前的那段日子,很多時候需要擴展Java 1.0.1的Date class。

          第一件待決事項是使用subclass或wrapper。subclassing是比較顯而易見的辦法:
          class mfDate extends Date {
              public nextDay() ...
              public dayOfYear() ...
          }

          wrapper則需要上委托(delegation):
          class mfDate {
              private Date _original;
          posted @ 2005-08-31 15:03 ivaneeo 閱讀(205) | 評論 (0)編輯 收藏

          作法(Mechanics)
            • 建立一個extension class,將它作為原物(原類)的subclass或wrapper。
            • 在extension class中加入轉型構造函數(converting constructors)。
                • ==》所謂[轉型構造函數]是指接受原物(original)作為參數。如果你采用subclassing方安,那么轉型構造函 數應該調用適當的superclass構造函數;如果你采用wrapper方案,那么轉型構造函數應該將它所獲得之引數(arument)賦值給[用以保 存委托關系(delegate)]的那個值域。
            • 在extension class中加入新特性。
            • 根據需要,將原物(original)替換為擴展物(extension)。
            • 將[針對原始類(original class)而定義的所有外加函數(foreign methods)]搬移到擴展類(extension)中。
          posted @ 2005-08-31 14:58 ivaneeo 閱讀(163) | 評論 (0)編輯 收藏

          動機(Motivation)
          如果你需要的額外函數超過兩個,外加函數(foreign methods)就很難控制住它們了。所以,你需要將這些函數組織在一起,放到一個恰當地方去。要達到這一目的,標準對象技術subclassing和 wrapping是顯而易見的辦法。這種情況下我把subclass或wrapper稱為local extension(本地擴展)。

          在subclass和wrapper之間做選擇時,我通常首先subclass。
          posted @ 2005-08-31 14:48 ivaneeo 閱讀(232) | 評論 (0)編輯 收藏

          你所使用的server class需要一些額外函數,但你無法修改這個class。

          建立一個新class,使它包含這些額外函數。讓這個擴展品成為source class的subclass(子類)或wrapper(外覆類)。

          Introduce_Local_Extension.png
          posted @ 2005-08-31 14:32 ivaneeo 閱讀(156) | 評論 (0)編輯 收藏

          僅列出標題
          共67頁: First 上一頁 42 43 44 45 46 47 48 49 50 下一頁 Last 
          主站蜘蛛池模板: 连城县| 朝阳县| 巨野县| 海盐县| 汝阳县| 礼泉县| 平邑县| 当雄县| 高淳县| 漳浦县| 孟连| 山西省| 乌拉特前旗| 库车县| 麻阳| 哈尔滨市| 勃利县| 蒙城县| 金山区| 山丹县| 衡阳市| 博野县| 鸡泽县| 长宁县| 玉环县| 和政县| 青岛市| 甘德县| 阜阳市| 广灵县| 龙口市| 会宁县| 溧阳市| 洪江市| 阿鲁科尔沁旗| 石门县| 毕节市| 千阳县| 乳源| 大同市| 印江|