Design(一)-Iterator设计模式

Iterator设计模式

简介:

Iterator设计模式在数据集合中按照顺序遍历集合. 英语单词Iterate有反复做某件事情的意思, 称为迭代器

例子说明:

名字说明
Aggregate表示集合的接口
Iterator遍历集合的接口
Book表示书的类
BookShelf表示书架的类
BookShelfIterator遍历书架的类
DesignApplicationTests所有的测试方法类

代码

Aggregate接口(Aggregate.java)

/**
 * 迭代器类
 *
 * @author MARKCC
 * @date 2019/2/6-16:32
 * @email markerccc@163.com
 */
public interface Aggregate {
    /**
     * 用于遍历集合的迭代器方法
     *
     * @return 迭代器类
     */
    Iterator iterator();
}

Iterator接口(Iterator.java)

/**
 * 用于遍历集合中的元素
 *
 * @author MARKCC
 * @date 2019/2/6-16:33
 * @email markerccc@163.com
 */
public interface Iterator {
    /**
     * 当集合中存在下一个元素的时候,该方法返回true
     *
     * @return Boolean
     */
    Boolean hasNext();

    /**
     * 返回的是集合中的下一个元素
     *
     * @return 集合中的下一个元素
     */
    Object next();
}

Book类(Book.java)

package com.mark.model.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.*;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;

/**
 * 书
 *
 * @author MARKCC
 * @date 2019/2/6-16:35
 * @email markerccc@163.com
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@TableName("book")
public class Book extends Model<Book> {

    private static final long serialVersionUID = 1L;

    @TableId
    private Long id;
    @TableField("create_time")
    private Date createTime;
    @TableField(value = "update_time", update = "now()")
    private Date updateTime;
    @TableField("del_flag")
    private String delFlag;
    @TableField("name")
    private String name;

    @Override
    protected Serializable pkVal() {
        return this.id;
    }
}

BookShelf类(BookShelf.java)

/**
 * 书架
 *
 * @author MARKCC
 * @date 2019/2/6-16:42
 * @email markerccc@163.com
 */
public class BookShelf implements Aggregate {
    private transient Book[] books;
    /**
     * ArrayList中用到了类似的用法, 请看modCount, modCount的用处是防止集合在遍历的时候被修改, 产生并发修改异常
     */
    private int last = 0;

    private int size;

    /**
     * 指定书架的最大容量
     *
     * @param maxsize 最大容量
     */
    public BookShelf(Integer maxsize) {
        this.size = maxsize;
        this.books = new Book[maxsize];
    }

    /**
     * 拿到索引位置上的书
     *
     * @param index 索引
     * @return 该索引上的书
     */
    public Book getBookAt(int index) {
        //这里借鉴ArrayList, 防止产生索引越界
        if (index >= size) {
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
        return books[index];
    }

    /**
     * 添加书本的方法
     *
     * @param book 书本
     */
    public void appendBook(Book book) {
        if (last >= size) {
            throw new IndexOutOfBoundsException(outOfBookOutMsg(last));
        }
        this.books[last] = book;
        last++;
    }

    /**
     * 获得长度
     *
     * @return
     */
    public int getLength() {
        return last;
    }

    @Override
    public Iterator iterator() {

        return new BookShelfIterator(this);
    }

    private String outOfBoundsMsg(int index) {
        // 返回当前的索引, 和元素个数
        return "Index: " + index + ", Size: " + size;
    }

    private String outOfBookOutMsg(int index) {
        return "Index: " + index + ", 书架Size: " + size;
    }
}

BookShelfIterator类(BookShelfIterator.java)

/**
 * @author MARKCC
 * @date 2019/2/6-16:58
 * @email markerccc@163.com
 */
public class BookShelfIterator implements Iterator {
    private BookShelf bookShelf;
    private int index;

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

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

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

测试方法:

/**
 * 迭代器设计模式
 */
@Test
public void iteratorTest() {
    BookShelf bookShelf = new BookShelf(3);
    bookShelf.appendBook(new Book(1L, new Date(), null, "0", "A"));
    bookShelf.appendBook(new Book(2L, new Date(), null, "0", "B"));
    bookShelf.appendBook(new Book(3L, new Date(), null, "0", "C"));
    Iterator iterator = bookShelf.iterator();
    while (iterator.hasNext()) {
        Book book = (Book) iterator.next();
        System.out.println(book.getName());
    }
}

分析

1. Iterator(迭代器)

该角色负责定义按顺序逐个遍历元素的接口(API)
方法作用
hasNext用于判断是否存在下一个元素
next用于获取元素

2. ConcreteIterator(具体的迭代器)

该角色负责实现Iterator角色所定义的接口(API)
扮演者作用
BookShelfIterator该角色包含了遍历集合所需的信息
字段作用
bookShelf实例
index指向的书的下标

3. Aggreagte(集合)

该角色负责创建Iterator角色的接口(API)
作用
它会创建出"按顺序访问保存在我内部元素的人
扮演者作用
Aggregate定义了iterator()

4. ConcreateAggregate(具体的集合)

该角色负责实现Aggregate角色所定义的接口(API)
作用
它会创建出具体的Iterator角色, 即ConcreteIterator角色
扮演者作用
BookShelf实现了Iterator方法

总结

1. 不管怎么如何变化, 都可以使用Iterator

while (iterator.hasNext()) {
    Book book = (Book) iterator.next();
    System.out.println(book.getName());
}
分析1 :
这里只使用了IteratorhasNext()next(), 并没有调用BookShelf的方法. 也就是说, 这里的while循环并不依赖于BookShelf实现
分析2 :
如果编写BookShelf的开发人员决定放弃数组来管理书本, 而是使用集合取代, 不管BookShelf如何变化, 只要BookShelfIterator都能正确的返回Iterator实例, 即不对上面的while循环做任何修改, 代码可以正常工作
分析3:
设计模式的作用就是帮助我们编写可复用的类. 所谓可复用, 就是将类实现为组件, 当一个组件发生改变时, 不需要对其他的组件进行修改, 或者只需要很小的修改即可, 这就是为什么Iterator的方法返回值是Iterator类型了, 而不是BookShelfIterator类了

2. 难以理解的抽象类和接口

分析:
人们常常使用ConcreateAggregate角色和ConcreateIterator角色编程, 而不使用AggregateIterator接口, 他们总想用具体的类来解决所有的问题. 这样很容易导致类之间的强耦合, 难以复用, 为了弱化类之间的耦合, 进而使类更加容易作为组件被再次利用, 需要常常使用抽象类和接口

3. 对应关系

AggregateIterator
ConcreateAggreagteConcreateIterator
分析:
如果BookShelf的实现发生了改变, 即getBookAt()发生改变, 我们必须修改BookShelfIterator

4. 下一个

分析:
next()方法是返回当前的元素, 并指向下一个元素

5. 最后一个

分析:
hasNext() 确认接下来是否可以调用next方法

6. 多个Iterator

分析:
将遍历功能置于Aggregate角色之外Iterator模式的一个特征. 根据这个特征, 可以针对一个ConcreateAggregate角色编写多个ConcreateIterator角色, 即一个集合可以编写多个迭代器

7. 迭代器的种类多种多样

种类
从最后开始向前遍历
即可以从前向后遍历, 也可以从后向前遍历(即有next()也有previous()
指定下标进行跳跃式的遍历

8. 不需要deleteIterator

分析:
Java中, 没有被使用的对象实例将会自动被删除(GC), 因此, 在Iterator中不需要与其对应的deleteIterator()

9. 相关的设计模式

Iterator模式没有在Iterator接口中对取出元素进行处理
Visitor模式遍历集合的过程中, 对元素进行相同的处理
Composite模式具有递归结构的模式, 在其中使用Iterator模式比较困难
Factory Method模式Iterator方法中生成Iterator的实例时可能会使用Factory Method模式
分析:
在遍历集合的过程中对元素进行固定的处理是常有的, Visitor模式正是为了应对这种需求出现的, 在访问元素集合的过程中对元素进行相同处理, 这种模式就是Visitor模式

借鉴

图解设计模式(结城浩 著)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值