Iterator(迭代器)模式

前言

  一直以来,我对设计模式总是模糊不清,感觉用到的地方并不多,直到正式工作后遇到了真正的难题,才发现设计模式是多么的重要。首先遇到的第一个问题是PM在开发过程中经常变更需求,这对于我们开发者来说是个难题,因为需求变了,对应的功能就要随之变更,如果需求变的太多,整个系统(软件)重构都有可能,这种碰到需求变更就要修改代码的情况真让人头疼。另外,leader让我研究一个开源项目(openTCS),其中简单的功能我大体可以明白,整个项目运行流程也很清晰,但是,唯一困难的是我对代码的设计原理搞不懂,我只知道其中有抽象类、接口,子类,实现类等等,但是它们有什么作用我不明白。当然还有很多难题,比如项目更新了,怎么让新旧版本都可用,怎么重构项目,重构理由是什么等等。所以,最终我下定决心好好学习设计模式,虽然有点亡羊补牢的感觉,但我认为这还不晚,而且这种认为自己能力不够,要通过学习来进步的态度一定要坚持下去。

Iterator模式

  Iterator模式是用于在数据集合中按顺序遍历集合,它的功能和for循环一样,for循环使用方法如下代码中所示:

int arr[] = {1, 3, 4, 10};
for (int i = 0; i < arr.length; i++){
    System.out.println(arr[i]);
}

  上面代码中的循环变量i代表数据集合中每个元素的排序位置,在数组中是从0开始,然后会递增为1,2,3,……,在大括号里对每个遍历的元素进行操作。这种每次使用都要声明一个循环变量,然后按照规则进行遍历的处理,好处是遍历规则一目了然,坏处是由于循环变量的存在,因为它代表每个元素在集合中的位置,每次获取集合中的元素都要用到这个循环变量,然而不同类型的集合,它获取元素的方式不一样,所以修改的地方很多。比如将上面代码中数组改成List类型:

List arr = new ArrayList();
arr.add(1);
arr.add(3);
arr.add(4);
arr.add(10);
for (int i = 0; i < arr.size(); i++){
   System.out.println(arr.get(i));
}

  由此可见,如果有很多的for循环使用了某个集合,当要修改这个集合的类型的时候,每一个for循环都要改变,这是很麻烦的事情。Iterator模式就是为了解决这个问题而产生的,它将遍历和实现分开了,也就是上述循环变量i的定义和使用那段代码重新封装成了一个方法,而用的时候直接调用即可,至于循环变量的递增都放在了封装的方法中,这样的好处是真正对集合进行遍历的地方就一个,也就是在封装的方法中,所以后期如果修改了集合的类型,只需要在封装方法中修改下代码即可,所以业务代码中用到的Iterator遍历方法都不要改动。
  下面是示例程序,需求是用Iterator模式对书架中的书进行遍历,并打印书的名称。

示例程序

1、Book类

package com.design.pattern1;

public class Book {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Book() {
    }

    public Book(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                '}';
    }
}

2、Iterator接口(Interface)
主要定义了循环遍历的方法。

package com.design.pattern1;

public interface Iterator {
    boolean hasNext();
    Object next();
}

3、Aggregate接口(Interface)
代表所有使用Iterator遍历的集合,不同的集合类或对象通过实现该接口的iterator方法,生成一个用于遍历集合的迭代器。

package com.design.pattern1;

public interface Aggregate {
    Iterator iterator();
}

4、BookShelf类(书架)
具体的集合类型,通过实现Aggregate接口生成一个迭代器(BookShelfIterator),并且将本书架类作为参数出传入BookShelfIterator类的构造方法中,实现遍历方法的个性化处理。

package com.design.pattern1;

public class BookShelf implements Aggregate{
    private Book[] books;
    private int last = 0;
    public BookShelf(int max){
        this.books = new Book[max];
    }
    public Book getBookAt(int index){
        return books[index];
    }
    public void appendBook(Book book){
        this.books[last] = book;
        last ++;
    }
    public int getLength(){
        return last;
    }

    @Override
    public Iterator iterator() {
        return new BookShelfIterator(this);
    }
}

5、BookShelfIterator类(实现Iterator接口)
BookShelf(书架)的迭代器实现类,该类实现了Iterator接口的遍历方法,并且通过构造方法中BookShelf参数传入书架的数据。

package com.design.pattern1;

public class BookShelfIterator implements Iterator {
    private BookShelf bookShelf;
    private int index;

    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    @Override
    public boolean hasNext() {
        if (index < bookShelf.getLength()){
            return true;
        }else {
            return false;
        }
    }

    @Override
    public Object next() {
        Book book = bookShelf.getBookAt(index);
        index ++;
        return book;
    }
}

6、Main类

package com.design.pattern1;

public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(3);
        bookShelf.appendBook(new Book("论语"));
        bookShelf.appendBook(new Book("史记"));
        bookShelf.appendBook(new Book("三国演义"));
        Iterator iterator = bookShelf.iterator();
        while (iterator.hasNext()){
            Book book = (Book) iterator.next();
            System.out.println(book.getName());
        }
    }
}

Iterator模式包含四个元素:
1、Iterator接口(迭代器)
主要负责定义按顺序遍历元素的方法。
2、ConcreteIteartor(具体的迭代器)
主要负责实现Iterator所定义的方法。
3、Aggregate接口(集合)
主要负责定义创建Iterator的方法。
4、ConcreteAggregate(具体的集合)
主要负责Aggregate定义的接口,它会创建出具体的Iterator迭代器,也就是上面的ConcreteIteartor。

使用抽象类和接口

  在大多数情况下,很多人喜欢用ConcreteIteartor和ConcreteAggregate编程,而不使用Iterator接口和Aggregate接口,他们总想用具体的类来解决所有的问题。
  但是如果只使用具体的类来解决问题,很容易导致类之间的强耦合,这些类也难以作为组件被再次利用。为了弱化类之间的耦合,进而使得类更加容易作为组件被再次使用,所以需要引入抽象类和接口。不要只使用具体类来编程,要优先使用抽象类和接口来编程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值