谁的青春不军训? 教官用了Iterator Pattern都说好

目的

不需要知道具体的数据存储方式对数据进行不同方式的遍历

例子代码

最近考答(so)题(suo) 获得了 10.24 元狗物券, 猛地想起抹茶妹妹不知道怎么样了, 兄弟告诉我 不努力就不是我兄弟 现在只要学习设计模式学的好, 女朋友就还在初中军训

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UzMDvDiN-1602385220804)(/assets/2019110100.png)]

比如我们有一个军训方队, 每天要点名, 这时候我们实现了如下代码:

先定义一个学生类:

@Data
@AllArgsConstructor
public class Student {

    private String name;

    private Boolean sexIsBoy;
}

我们需要按照从左到右的顺序进行报名:

public static final void printAllName(
        List<List<Student>> students) {
    for (List<Student> studentList : students) {
        for (Student student : studentList) {
            System.out.println(student.getName());
        }
    }
}

我们试验一下:

List<List<Student>> students = new ArrayList<>(16);
for (int i = 0; i < 10; i++) {
    students.add(Arrays.asList(
            new Student("朱坚强" + i, true),
            new Student("兰兰" + i, false),
            new Student("codog编程狗" + i, true)));
}
printAllName(students);

问题分析

这个代码我们认为有二处可能有隐患的地方: 一处是我们存储学生队列的这个结构(list<list>) 可能会改变, 另外一处是我们目前只支出从左到右访问, 如果有新的遍历要求我们就需要更新大量的上层代码, 我们写完了这个代码, 想要回家陪(da)老(fei)婆(ji), 结果走到半路上, 被叫着改了二个需求, 一个是把 list<list> 改成二维数据方式存储, 另外一个是需要队列中的女生单独报, 男生不报名了, 这时候我们说 printAllName 这个方法用了1万处了, 需要逐个改

迭代器模式

先定义一个学生队列类:

@Data
@AllArgsConstructor
public class StudentLineUp {
    private List<List<Student>> students;
}

定义一个迭代器:

public class LineUpIterator 
            implements Iterator<Student> {

    private StudentLineUp studentLineUp;
    private Integer totalCount;
    private Integer currentRow;
    private Integer currentCol;
    private Integer currentCount;

    public LineUpIterator(
                StudentLineUp studentLineUp) {
        this.studentLineUp = studentLineUp;
        this.totalCount = studentLineUp
                .getStudents()
                .stream().map(list -> list.size())
                .reduce(Integer::sum).get();
        this.currentRow = 0;
        this.currentCol = 0;
        this.currentCount = 0;
    }

    @Override
    public boolean hasNext() {
        return currentCount
                .compareTo(totalCount) < 0;
    }

    @Override
    public Student next() {
        if(!hasNext()) {
            throw new RuntimeException
                        ("没有下一个数据了");
        }
        if(studentLineUp.getStudents()
            .get(currentRow).size() <= currentCol) {
            currentRow++;
            currentCol = 0;
        }
        currentCount++;
        return studentLineUp.getStudents()
                .get(currentRow).get(currentCol++);
    }
}

实际使用:

List<List<Student>> students = new ArrayList<>(16);
for (int i = 0; i < 10; i++) {
    students.add(Arrays.asList(
            new Student("朱坚强" + i, true),
            new Student("兰兰" + i, false),
            new Student("codog编程狗" + i, true)));
}
LineUpIterator lineUpIterator = 
new LineUpIterator(new StudentLineUp(students));
while (lineUpIterator.hasNext()) {
    System.out.println(lineUpIterator.next().getName());
}

更进一步

如果我们变化的维度减少一个, 比如说是这个遍历方式基本不变, 但是内部存储方式可能会变, 那我们可以对数据结构采用 Iterable 方式:

@Data
@AllArgsConstructor
public class StudentLineUp implements Iterable<Student> {
    private List<List<Student>> students;

    @Override
    public Iterator<Student> iterator() {
        return new LineUpIterator(this);
    }
}

使用方式:

List<List<Student>> students = new ArrayList<>(15);
for (int i = 0; i < 10; i++) {
    students.add(Arrays.asList(
            new Student("朱坚强" + i, true),
            new Student("兰兰" + i, false),
            new Student("codog编程狗" + i, true)));
}
for (Student student : new StudentLineUp(students)) {
    System.out.println(student.getName());
}

类图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KFFNT5xO-1602385220807)(/assets/2019110101.png)]
微信:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值