Java设计模式 -- 迭代器模式

liu87710 8年前
   <p>迭代器模式: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。</p>    <p>比如说,现在我们有两个聚合对象,一个是数组,一个是 ArrayList , 利用这两个对象分别存储文理科课程信息,像下面这样。</p>    <pre>  <code class="language-java">public class LiberalLessons {        public static final int MAX_LESSONS = 3;      private int numberOfLessons = 0;      private String[] lessons;        public LiberalLessons() {          lessons = new String[MAX_LESSONS];          addLessons("Political");          addLessons("Geography");          addLessons("History");      }        private void addLessons(String lesson) {          lessons[numberOfLessons] = lesson;          numberOfLessons++;      }        public String[] getLessons() {          return lessons;      }  }    public class ScienceLessons {      private ArrayList<String> lessons;        public ScienceLessons() {          lessons = new ArrayList<>();          addLessons("Physical");          addLessons("Chemical");          addLessons("Biological");      }        private void addLessons(String lesson) {          lessons.add(lesson);      }        public ArrayList getLessons() {          return lessons;      }  }</code></pre>    <p>可见,以上我们将信息保存在了不同的聚合对象中,那么如果我们想要同时打印文理科的课程,该怎么办呢?</p>    <pre>  <code class="language-java">public class PrintHelper {      private LiberalLessons liberalLessons;      private ScienceLessons scienceLessons;        public PrintHelper(LiberalLessons liberalLessons, ScienceLessons scienceLessons) {          this.liberalLessons = liberalLessons;          this.scienceLessons = scienceLessons;      }        public void print() {          printLiberalLessons();          printScienceLessons();      }        private void printLiberalLessons() {          String[] lessons = liberalLessons.getLessons();          System.out.println("Liberal Lessons : ");          for (int i = 0; i < LiberalLessons.MAX_LESSONS; i++) {              System.out.print(lessons[i] + "\t");          }          System.out.println();      }        private void printScienceLessons() {          ArrayList<String> lessons = scienceLessons.getLessons();          System.out.println("Science Lessons : ");          for (int i = 0; i < lessons.size(); i++) {              System.out.print(lessons.get(i) + "\t");          }          System.out.println();      }  }    public class Client {      public static void main(String[] args) {          LiberalLessons liberalLessons = new LiberalLessons();          ScienceLessons scienceLessons = new ScienceLessons();            PrintHelper printHelper = new PrintHelper(liberalLessons, scienceLessons);          printHelper.print();      }  }</code></pre>    <p>可见,在这里我又多写了一个辅助类 PrintHelper , 这样可以减少主函数中的代码量,我个人不太喜欢在主函数写太多的代码。</p>    <p>来看看,由于我们使用了不同的聚合对象,导致我们不得不区别对待,如果有一种方法,能够让我们不管是针对哪种聚合对象都可以进行相同的操作就好了,这正是迭代器应该做的工作。</p>    <p>首先,我们看看 java.util.Iterator 接口</p>    <pre>  <code class="language-java">public interface Iterator<E> {      boolean hasNext();      E next();      void remove();  }</code></pre>    <p>hasNext() 方法返回一个布尔值,让我们知道是否还有更多的元素。</p>    <p>next() 方法返回下一个元素的值。</p>    <p>remove() 用于删除由 next() 方法返回的最后一项。</p>    <p>下面我们就利用 Iterator 对以上代码进行改写。</p>    <pre>  <code class="language-java">public class LiberalIterator implements Iterator<String> {        private String[] lessons;      private int position = 0;        public LiberalIterator(String[] lessons) {          this.lessons = lessons;      }        @Override      public boolean hasNext() {          if (position >= lessons.length) {              return false;          }          return true;      }        @Override      public String next() {          String lesson = lessons[position];          position += 1;          return lesson;      }        @Override      public void remove() {          throw new UnsupportedOperationException("You can not remove element !");      }  }</code></pre>    <p>我们针对文科课程类写了一个迭代器,在 remove() 方法中我们抛出了一个异常,表示我们不希望客户端通过迭代器删除元素。实际上我们也只需要写这么一个迭代器类,因为在 ScienceLessons 类中我们使用的是 ArrayList ,它是自带 Iterator 的,我们只需要调用 iterator() 方法即可。</p>    <p>接下来,我们就将 LiberalLessons 和 ScienceLessons 中的 getLessons() 方法进行改写,写成 createIterator() 方法。</p>    <pre>  <code class="language-java">public Iterator<String> createIterator() {      return new LiberalIterator(lessons);  }  public Iterator<String> createIterator() {      return lessons.iterator();  }</code></pre>    <p>现在再看看我们的 PrintHelper 该怎么书写代码。</p>    <pre>  <code class="language-java">public class PrintHelper {      private LiberalLessons liberalLessons;      private ScienceLessons scienceLessons;        public PrintHelper(LiberalLessons liberalLessons, ScienceLessons scienceLessons) {          this.liberalLessons = liberalLessons;          this.scienceLessons = scienceLessons;      }        public void print() {          System.out.println("Liberal Lessons : ");          Iterator<String> liberalIterator = liberalLessons.createIterator();          print(liberalIterator);          System.out.println();            System.out.println("Science Lessons : ");          Iterator<String> scienceIterator = scienceLessons.createIterator();          print(scienceIterator);          System.out.println();          }        private void print(Iterator<String> iterator) {          while (iterator.hasNext()) {              System.out.print(iterator.next() + "\t");          }      }  }</code></pre>    <p>这样的话,我们就可以不必区分聚合对象,只需要根据类中提供的迭代器就可以访问元素,而且这个时候我们也不知道类的内部用的是哪种聚合类型。</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/3590449fabdf</p>    <p> </p>