<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

    范例(Examples)
    Java 2擁有一組全新群集(collections)--并非僅僅加入一些新classes,而是完全改變了群集的風格.所以在Java 1.1Java 2中,封裝群集的方式也完全不同.我首先討論Java 2的方式,因為我認為功能更強大的Java 2 collections會取代Java 1.1 collections的地位.

    范例(Examples): Java 2

    假設有個人要去上課.我們用一個簡單的Course來表示[課程]:
    class Course...
       public Course(String name, boolean isAdvanced) {...};
       public boolean isAdvanced() {...};

    我不關心課程其他細節.我感興趣的是表示[人]的Person:
    class Person...
       public Set getCourse() {
          return _courses;
       }
       public void setCourse(Set arg) {
          _courses = arg;
       }
       private Set _courses;

    有了這個接口,我們就可以這樣為某人添加課程:
       Person kent = new Person();
       Set s = new HashSet();
       s.add(new Course("Smalltalk Programming", false));
       s.add(new Course("Appreciating Single Malts", true));
       kent.setCourses(s);
       Assert.equals(2, Kent.getCourses().size());

       Course refact = new Course("Refactoring", true);
       kent.getCourses().add(refact);
       kent.getCourses().add(new Course("Brutal Sarcasm", false));
       Assert.equals(4, kent.getCourses().size());

       kent.getCourses().remove(refact);
       Assert.equals(3, kent.getCourses().size());
    如果想了解高級課程,可以這么做:
       Iterator iter = person.getCourses().iterator();
       int count = 0;
       while(iter.hasNext()) {
          Course each = (Course)iter.next();
          if(each.isAdvanced()) count++;
       }
    我要做的第一件事就是為Person中的群集(collections)建立合適的修改函數(modifiers, 亦即add/remove函數),如下所示,然后編譯:
    class Person...
       public void addCourse(Course arg) {
          _courses.add(arg);
       }
       public void removeCourse(Course arg) {
          _courses.remove(arg);
       }

    如果我想下面這樣初始化_courses值域,我的人生會輕松得多:
       private Set _courses = new HashSet();

    接下來我需要觀察設值函數(setter)的調用者.如果有許多地點大量運用了設值函數,我就需要修改設值函數,令它調用添加/移除(add/remove)函數.這個過程的復雜度取決于設值函數的被使用方式.設值函數的用法有兩種,最簡單的情況就是:它被用來[對集群進行初始化動作].換句話說,設值函數被調用之前,_courses是個空群集.這種情況下我需要修改設值函數,令它調用添加函數(add)就行了:
    class Person...
       public void setCourses(Set arg) {
          Assert.isTrue(_courses.isEmpty());
          Iterator iter = arg.iterator();
          while(iter.hasNext()) {
             addCourse((Course)iter.next());
          }
       }
    修改完畢后,最后以Rename Method(273)更明確地展示這個函數的意圖.
       public void initializeCourses(Set arg) {
          Assert.isTrue(_courses.isEmpty());
          Iterator iter = arg.iterator();
          while(iter.hasNext()) {
             addCourse((Course)iter.next());
          }
       }

    更普通的情況下,我必須首先以移除函數(remove)將群集中的所有元素全部移除,然后再調用添加函數(add)將元素一一添加進去.不過我發現這種情況很少出現(唔,愈是普通的情況,愈少出現).

    如果我知道初始化時,除了添加元素,不會再有其他行為,那么我可以不使用循環,直接調用addAll()函數:
       public void initializeCourses(Set arg) {
          Assert.isTrue(_courses.isEmpty());
          
    _courses.addAll(arg);
       }

    我不能僅僅對這個set賦值,就算原本這個set是空的也不行.因為萬一用戶在[把set傳遞給Person對象]之后又去修改它,會破壞封裝.我必須像上面那樣創建set的一個拷貝.

    如果用戶僅僅只是創建一個set,然后使用設值函數(setter.譯注:目前已改名為initializeCourses()),我可以讓它們直接使用添加/移除(add/remove)函數,并將設值函數完全移除.于是,以下代碼:
       Person kent = new Person();
       Set s = new HashSet();
       s.add(new Course("Smalltalk Programming", false));
       s.add(new Course("Appreciating Single Malts", true));
       kent.initializeCourses(s);

    就變成了:
       Person kent = new Person();
       kent.addCourse(new Course("Smalltalk Programming", false));
       kent.addCourse(new Course("Appreciating Single Malts", true));



    接下來我開始觀察取值函數(getter)的使用情況.首先處理[有人以取值函數修改底部群集(underlying collection)]的情況,例如:
       kent.getCourses().add(new Course("Brutal Sarcasm", false));
    這種情況下我必須加以改變,使它調用新的修改函數(modifier):
       kent.addCourse(new Course("Brutal Sarcasm", false));
    修改完所有此類情況之后,我可以讓取值函數(getter)返回一個只讀映件(read-only view),用以確保沒有任何一個用戶能夠通過取值函數(getter)修改群集:
       public Set getCourses() {
          return Collections.unmodifiableSet(_courses);
       }
    這樣我就完成了對群集的封裝.此后,不通過Person提供的add/remove函數,誰也不能修改群集內的元素.

    將行為移到這個class中

    我擁有了合理的接口.現在開始觀察取值函數(getter)的用戶,從中找出應該屬于Person的代碼.下面這樣的代碼就應該搬移到Person去:
       Iterator iter = person.getCourses().iterator();
       int counter = 0;
       while(iter.hasNext()){
          Course each = (Course)iter.next();
          if(each.isAdvanced()) cout++;
       }

    因為以上只使用了屬于Person的數據.首先我使用Extract Method(110)將這段代碼提煉為一個獨立函數:
       int numberOfAdvancedCourses(Person person) {
          Iterator iter = person.getCourses().iterator();
          int count = 0;
          while(iter.hasNext()) {
             Course each = (Course)iter.next();
             if(each.isAdvanced()) count++;
          }
          return count;
       }
    然后使用Move Method(142)將這個函數搬移到Person中:
    class Person...
       int numberOfAdvancedCourses(Person person) {
          Iterator iter = person.getCourses().iterator();
          int count = 0;
          while(iter.hasNext()) {
             Course each = (Course)iter.next();
             if(each.isAdvanced()) count++;
          }
          return count;
       }

    舉個常見例子,下列代碼:
       kent.getCourses().size();
    可以修改更具可讀性的樣子,像這樣:

    kent.numberOfCourses();

    class Person...
    public int numberOfCourses() {
       return _courses.size();
    }

    數年以前,我曾經擔心將這樣的行為搬移到Person中會導致Person變得臃腫.但是在實際工作經驗中,我發現這通常并不成為問題.

    posted on 2005-09-19 13:51 ivaneeo 閱讀(546) 評論(0)  編輯  收藏 所屬分類: refactoring-從地獄中重生
    主站蜘蛛池模板: 亚洲邪恶天堂影院在线观看| 亚洲情综合五月天| 一区二区三区免费高清视频| 精品亚洲综合在线第一区| 99在线精品视频观看免费| 久久久久久久久无码精品亚洲日韩 | 国产成人久久精品亚洲小说| 亚洲人AV永久一区二区三区久久| 在线观看特色大片免费网站| 精品日韩99亚洲的在线发布| 亚洲AV网站在线观看| 84pao强力永久免费高清| 国产成人高清亚洲一区久久| 亚洲国产天堂久久综合网站| 国产精品视频免费一区二区三区| 男的把j放进女人下面视频免费| 亚洲精品无码久久久久A片苍井空| 国产AV无码专区亚洲AWWW| 青青草免费在线视频| 两个人看的www免费| 亚洲精品无码成人片久久不卡| 亚洲AV综合色一区二区三区| 国产在线观看免费视频播放器| 无码人妻一区二区三区免费看| 国产AV日韩A∨亚洲AV电影 | 亚洲欧洲自拍拍偷综合| 亚洲日韩国产一区二区三区| 久久久久国色AV免费观看性色 | 亚洲精品无码专区久久同性男| 国产成人免费在线| 中文在线免费看视频| 国产精品亚洲专区无码不卡| 亚洲成a人片在线观看中文!!!| 亚洲热线99精品视频| 免费一级成人毛片| 69成人免费视频无码专区| 美女内射无套日韩免费播放| 高清永久免费观看| 国产成人综合亚洲绿色| 亚洲人成77777在线播放网站不卡| 亚洲国产成人私人影院|