16.java設計模式之迭代器模式

基本需求:

  • 展現一個學校的結構,好比一個學校下面有多個學院,學院下面有多個系,對其節點主要是遍歷,與組合模式略有不一樣

傳統方案:

  • 學校<-學院<-系 依次繼承
  • 這種方式,在一個頁面中展現出學校的院系組成,一個學校有多個學院,一個學院有多個系,所以這種方案,不能很好實現的遍歷的操做,而且他們之間也沒有繼承關係,使用繼承並不合適

基本介紹:

  • 迭代器模式(Iterator)是經常使用的設計模式,屬於行爲型模式,這種模式用於順序訪問集合對象的元素,不須要知道集合對象的底層表示java

  • 若是咱們的集合元素是用不一樣的方式實現的,有數組,還有java的集合類,或者還有其餘方式,當客戶端要遍歷這些集合元素的時候就要使用多種遍歷方式,並且還會暴露元素的內部結構,能夠考慮使用迭代器模式解決設計模式

  • 迭代器模式提供一種遍歷集合元素的統一接口,用一致的方法遍歷集合元素,不須要知道集合對象的底層表示,即:不暴露其內部的結構數組

  • 把在元素之間遊走的責任交給迭代器,而不是聚合對象安全

  • 因爲迭代器模式將存儲數據和遍歷數據的職責分離,增長新的聚合類須要對應增長新的迭代器類,類的個數成對增長,這在必定程度上增長了系統的複雜性服務器

  • UML類圖(原理)網絡

    • 說明
      • Iterator:迭代器接口,直接使用JDK提供的便可提供,含有hasNext, next, remove
      • ConcreteIterator:具體的迭代器類,進行元素迭代,其內部元素的以不一樣的方式進行存儲,例如數組、list等
      • Aggregate:一個統一的聚合接口,將客戶端和具體聚合解耦,進行元素的存儲
      • ConcreteAggreage:具體的聚合持有對象集合,並提供一個方法,返回一個迭代器,該迭代器能夠正確遍歷集合,和ConcreteIterator一一對應
      • Element:集合內部所存儲的元素
      • 實際狀況中通常將ConcreteIterator做爲內部類放入ConcreteAggreage類中,直接省去了元素集合elementes的傳遞
  • UML類圖(案例)dom

    • 說明
      • OutputImpl:用於輸出信息的輔助類
  • 代碼實現ide

    • 迭代器類不做爲持有迭代集合類的內部類大數據

      • @Data
        @AllArgsConstructor
        public class Department {
        
           // 迭代器內部元素
        
           private String name;
        
           private String description;
        
        }
      • public class ComputerCollegeIterator implements Iterator {
        
           // 計算機學院迭代器,元素使用數組存儲 通常會將迭代器實現類做爲須要迭代對象的內部類
        
           private Department[] departments;
        
           // 當前位置指針
           private int index = 0;
        
           public ComputerCollegeIterator(Department[] departments) {
               this.departments = departments;
           }
        
           // 判斷是否有下一個元素
           @Override
           public boolean hasNext() {
               return !(this.index >= this.departments.length);
           }
        
           // 返回下一個元素
           @Override
           public Department next() {
               return this.departments[this.index++];
           }
        
           @Override
           public void remove() {
               // 移除方法空實現
           }
        
        }
      • public class InfoCollegeIterator implements Iterator {
        
           // 信息工程學院迭代器,元素使用List集合存儲 通常會將迭代器實現類做爲須要迭代對象的內部類
        
           private List<Department> departments;
        
           // 當前位置指針
           private int index = 0;
        
           public InfoCollegeIterator(List<Department> departments) {
               this.departments = departments;
           }
        
           // 判斷是否有下一個元素
           @Override
           public boolean hasNext() {
               return !(this.index >= this.departments.size());
           }
        
           // 返回下一個元素
           @Override
           public Department next() {
               return this.departments.get(this.index++);
           }
        
           @Override
           public void remove() {
               // 移除方法空實現
           }
        
        }
      • public interface College {
        
           // 學院接口
        
           // 獲取學院名稱
           String getName();
        
           // 給學院內部添加系
           void addDepartment(String name, String description);
        
           // 獲取該學院所對應的迭代器
           Iterator createIterator();
        
        }
        
        // 實現類一 計算機學院
        class ComputerCollege implements College {
        
           // 存儲內部元素的集合,用於獲取迭代器
           private Department[] departments;
        
           // 當前元素位置指針
           private int index;
        
           public ComputerCollege() {
               this.departments = new Department[5];
               this.index = 0;
               addDepartment("Java專業", "Java專業 ");
               addDepartment("PHP專業", "PHP專業 ");
               addDepartment("大數據專業", "大數據專業");
           }
        
           @Override
           public String getName() {
               return "計算機學院";
           }
        
           @Override
           public void addDepartment(String name, String description) {
               Department department = new Department(name, description);
               this.departments[this.index++] = department;
           }
        
           @Override
           public Iterator createIterator() {
               return new ComputerCollegeIterator(this.departments);
           }
        
        }
        
        // 實現類二 信息工程學院
        class InfoCollege implements College {
        
           // 存儲內部元素的集合,用於獲取迭代器
           private List<Department> departments;
        
           public InfoCollege() {
               this.departments = new ArrayList<Department>();
               addDepartment("信息安全專業", "信息安全專業");
               addDepartment("網絡安全專業", "網絡安全專業");
               addDepartment("服務器安全專業", "服務器安全專業");
           }
        
           @Override
           public String getName() {
               return "信息工程學院";
           }
        
           @Override
           public void addDepartment(String name, String description) {
               this.departments.add(new Department(name, description));
           }
        
           @Override
           public Iterator createIterator() {
               return new InfoCollegeIterator(this.departments);
           }
        
        }
      • public class OutputImpl {
        
           // 輸出迭代器元素內部的實現類
        
           private List<College> colleges;
        
           public OutputImpl(List<College> colleges) {
               this.colleges = colleges;
           }
        
           public void printCollege() {
               // 獲取List集合內部的迭代器
               Iterator<College> iterator = colleges.iterator();
               while (iterator.hasNext()) {
                   College college = iterator.next();
                   System.out.println("======" + college.getName() + "======");
                   // 獲取學院內部系的迭代器進行迭代輸出 而不須要知道元素再內部以什麼形式的集合存在,統一了遍歷方式
                   printDepartment(college.createIterator());
               }
           }
        
           private void printDepartment(Iterator iterator) {
               while (iterator.hasNext()) {
                   Department department = (Department) iterator.next();
                   if (null != department) {
                       System.out.println(department.getName() + "-----" + department.getDescription());
                   }
               }
           }
           
        }
      • public class Client {
           public static void main(String[] args) {
               // 建立學院的集合
               List<College> colleges = new ArrayList<College>();
               colleges.add(new ComputerCollege());
               colleges.add(new InfoCollege());
               // 建立輸出類 並迭代輸出學院及其下面的系
               OutputImpl output = new OutputImpl(colleges);
               output.printCollege();
           }
        }
    • 迭代器類做爲持有迭代集合類的內部類this

      • // 實現類一 計算機學院
        public class ComputerCollege implements College {
        
           // 存儲內部元素的集合,用於獲取迭代器
           private Department[] departments;
        
           // 當前元素位置指針
           private int index;
        
           public ComputerCollege() {
               this.departments = new Department[5];
               this.index = 0;
               addDepartment("Java專業", "Java專業 ");
               addDepartment("PHP專業", "PHP專業 ");
               addDepartment("大數據專業", "大數據專業");
           }
        
           @Override
           public String getName() {
               return "計算機學院";
           }
        
           @Override
           public void addDepartment(String name, String description) {
               Department department = new Department(name, description);
               this.departments[this.index++] = department;
           }
        
           @Override
           public Iterator createIterator() {
               return new ComputerCollegeIterator();
           }
        
           // 迭代器類做爲持有迭代集合類的內部類
           private class ComputerCollegeIterator implements Iterator {
        
               // 計算機學院迭代器,元素使用數組存儲 通常會將迭代器實現類做爲須要迭代對象的內部類
        
               // 當前位置指針
               private int index = 0;
        
               // 判斷是否有下一個元素 直接使用上層類的元素集合便可
               @Override
               public boolean hasNext() {
                   return !(this.index >= ComputerCollege.this.departments.length);
               }
        
               // 返回下一個元素 直接使用上層類的元素集合便可
               @Override
               public Department next() {
                   return ComputerCollege.this.departments[this.index++];
               }
        
               @Override
               public void remove() {
                   // 移除方法空實現
               }
        
           }
        
        }
      • // 實現類二 信息工程學院
        public class InfoCollege implements College {
        
           // 存儲內部元素的集合,用於獲取迭代器
           private List<Department> departments;
        
           public InfoCollege() {
               this.departments = new ArrayList<Department>();
               addDepartment("信息安全專業", "信息安全專業");
               addDepartment("網絡安全專業", "網絡安全專業");
               addDepartment("服務器安全專業", "服務器安全專業");
           }
        
           @Override
           public String getName() {
               return "信息工程學院";
           }
        
           @Override
           public void addDepartment(String name, String description) {
               this.departments.add(new Department(name, description));
           }
        
           @Override
           public Iterator createIterator() {
               return new InfoCollegeIterator();
           }
        
           // 迭代器類做爲持有迭代集合類的內部類
           private class InfoCollegeIterator implements Iterator {
        
               // 信息工程學院迭代器,元素使用List集合存儲 通常會將迭代器實現類做爲須要迭代對象的內部類
        
               // 當前位置指針
               private int index = 0;
        
               // 判斷是否有下一個元素 直接使用上層類的元素集合便可
               @Override
               public boolean hasNext() {
                   return !(this.index >= InfoCollege.this.departments.size());
               }
        
               // 返回下一個元素 直接使用上層類的元素集合便可
               @Override
               public Department next() {
                   return InfoCollege.this.departments.get(this.index++);
               }
        
               @Override
               public void remove() {
                   // 移除方法空實現
               }
        
           }
        
        }

jdk源碼:

  • 在jdk的ArrayList源碼中就使用到了迭代器模式

  • UML類圖

    • 說明

      • List就是充當了聚合接口,含有一個iterator()方法,返回一個迭代器對象

      • ArrayList是實現聚合接口List的子類,實現了iterator()

      • ArrayList內部的elementData屬性就是存放元素的集合,是一個數組Object[]

      • Itr充當具體實現迭代器Iterator的類,做爲ArrayList內部類

      • Iterator接口JDk提供

      • public class ArrayList<E> extends AbstractList<E>
               implements List<E>, RandomAccess, Cloneable, java.io.Serializable
        {
           // 存儲元素的集合
           transient Object[] elementData;
           
           // 實現獲取迭代器方法
           public Iterator<E> iterator() {
               return new Itr();
           }
        
           /**
            * An optimized version of AbstractList.Itr
            */
           // 做爲ArrayList內部類 實現迭代器Iterator
           private class Itr implements Iterator<E> {
              ......
           }
        }

注意事項:

  • 提供一個統一的方法遍歷對象,客戶不用再考慮聚合的類型,使用一種方法就能夠遍歷對象了
  • 隱藏了聚合的內部結構,客戶端要遍歷聚合的時候只能取到迭代器,而不會知道聚合的具體組成
  • 提供了一種設計思想,就是一個類應該只有一個引發變化的緣由(叫作單一責任原則)。在聚合類中,咱們把迭代器分開,就是要把管理對象集合和遍歷對象集合的責任分開,這樣一來集合改變的話,隻影響到聚合對象。而若是遍歷方式改變的話,隻影響到了迭代器
  • 當要展現一組類似對象,或者遍歷一組相同對象時使用, 適合使用迭代器模式
  • 每一個聚合對象都要一個迭代器,會生成多個迭代器很差管理類
相關文章
相關標籤/搜索