迭代器模式

迭代器模式定义
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

Java 开发过程中遍历是常用的。如下边程序

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

for语句中i++每次循环自增1,迭代到下一元素。将循环变量的作用抽象化,通用化后形成的模式,在设计模式中成为Iterator模式。

实现场景
将书(Book)放到书架(BookShelf)中,并将书名按顺序显示。

UML

image.png
名字 说明
Aggregate 标识集合的接口
Iterator 遍历集合的接口
Book 表示书的类
Book 表示书架的类
BookShelfIterator 遍历书架的类
Main 测试类

<meta charset="utf-8">

程序示例

Aggregate 接口

所要便利的集合的接口。实现了该接口的类将成为一个可以保存多个元素的集合,类似数组。

public interface Aggregate{
    public abstract Iterator iterator();
}

Aggregate接口中声明的方法为iterator,作用为生成一个用于遍历的迭代器。

Iterator 接口

作用为遍历集合中元素,相当于循环语句中的循环变量(for(int i =0 ;i<arr.lenth;i++),具体实现一个顺序遍历的迭代器。

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

hasNext() 方法判断是否存在下一个,next()方法获取下一个元素。
特殊说明下,next方法在获取元素的同时,要将计数器向下一个元素的计数加一。获取的是当前元素,并指向下一个元素。

Book类

普通类,书名field 获取书名的getName()方法。构造函数初始化书名。

public class Book{
    private String name ;
    public Book(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}

BookShelf 类

书架类,作为存放书的集合类,实现Aggregate接口。实现了Aggregate接口的iterator方法。

public class BookShelf implements Aggregate {

    private List<Book> books;

    public BookShelf() {
        this.books = new ArrayList<Book>();
    }

    public Book getBookAt(int index) {
        return books.get(index);
    }

    public void appendBook(Book book) {
        books.add(book);
    }

    public int getLength() {
        return books.size();
    }

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

主要点在iterator方法,方法返回了遍历书架时要用的BookShelfIterator类作为书架的迭代器。当外部要遍历书架时会调用该方法。

BookShelfIterator类
public class BookShelfIterator implements Iterator {

    private BookShelf bookShelf;
    private int index;

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

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

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

作为一个迭代器,要实现Iterator接口。index为迭代器当前所指向的下标。
hasNext判断还有没有下一本。通过下标和总数比较判断。
next获取当前书,并指向下一个。

Main类

public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf();
        bookShelf.appendBook(new Book("Around the World in 80 Days"));
        bookShelf.appendBook(new Book("Bible"));
        bookShelf.appendBook(new Book("Cinderella"));
        bookShelf.appendBook(new Book("Daddy-Long-Legs"));
        Iterator it = bookShelf.iterator();
        while (it.hasNext()) {
            Book book = (Book) it.next();
            System.out.println(book.getName());
        }
    }
}

控制台:
----------------------------------
Around the World in 80 Days
Bible
Cinderella
Daddy-Long-Legs
----------------------------------

Iterator模式中各角色的作用

Iterator(迭代器)

该角色责任定义按顺序逐个遍历元素的接口。
程序中,由Iterator接口扮演,定义了hasNext和next两个方法。

Concretelterator(具体的迭代器)

该角色负责实现Iterator角色所定义的接口.该角色包含了遍历集合所必须的信息。

Aggregate(集合)

该角色负责定义创建Iterator角色的接口。这个接口是一个方法会创建出一个,按照顺序访问保存在我内部元素的人。

ConcreteAggregate(具体集合)

该角色负责实现Aggregate角色所定义的接口。他会创建出具体的Iterator角色,也就是ConcreteIterator,也就是实例中的BookShelf。
Iterator 模式的类图

image

学习设计模式的重点

不管实现如何变化都可以使用Iterator

为什么一定要考虑引入Iterator这种复杂的设计模式呢?

如果是数组,直接使用for玄幻语句进行遍历处理不就可以了吗?

为什么要在集合之外引入Iterator角色?

一个重要的理由:引入Iterator后可以将遍历与实现分离开来。

  while (it.hasNext()) {
            Book book = (Book) it.next();
            System.out.println(book.getName());
        }

这里使用了Iterator的hasNext方法和next方法,并没有调用BookShelf的方法。也就是说,这里的while循环并不依赖于BookShelf的实现。

例如在BookShelf的开发人员决定放弃用数组来管理书本,而是用Java.util.Vector取而代之,会怎么样呢。不管BookShelf如何变化,只要BookShelf的iterator方法能正确的返回Iterator的实力,即使不对上面的while循环做任何修改,代码都可以正常工作。

对于BookShelf的调用者来说真的太方便了。

设计模式的作用就是帮助我们编写可复用的类。

所谓可复用,就是指将类实现为组件,当一个组件发生改变时,不需要对其他组件进行修改或是只需要很小的修改即可应对。

这也就能理解为什么在示例程序中iterator方法返回值不是bookshelfiter类而是iter类型了。这表明,程序就是要使用iterator的方法进行编程而不是bookshelfiterator的方法。

难以理解抽象类和接口

难以理解抽象类和接口的人常常食用ConcreteAggregate角色和ConcreteIterator角色编程,而不是用Aggregate接口和Iterator接口,他们总想用具体的类解决所有的问题。

但是如果只使用具体的类来解决问题,很容易导致类之间的强耦合,这些类也难以作为组件被再次利用,为了弱化类之间的耦合,进而使得类更加容易作为组件被再次利用,我们需要引入抽象类和接口。
这种思想要贯穿整个设计模式。

Aggregate和Iterator的对应
多个Iterator

将遍历功能至于Aggregate角色之外是Iterator模式的一个特征。这个特征可以针对一个ConcreteAggregate角色编写多个ConcreteIterator角色。

预先介绍几种设计模式:

Vistor模式

iterator模式是从集合中一个一个取出元素进行遍历,但是并没有在Iterator接口中生病对取出的元素进行任何处理。

Vistor模式则在遍历元素集合的过程中,对元素进行相同的处理。

在遍历集合的过程中对元素进行固定的处理是常有的需求。Visitor模式正是为了应对这种需求而出现的。在方文元素集合的过程中对元素进行相同的处理,这种模式就是Vistor模式。

Composite模式

Composite模式是具有递归结构的模式,在其中使用Iterator模式比较困难。

Factory Method 模式

在iterator方法中生成Iterator的实力时可能会使用Factory Method模式。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容