设计模式之迭代器模式

前言 :

为什么要引入这种Iterator这种模式?

        数组直接用for循环不就好了吗~重要的理由就是可以将遍历与实现分离开来。

目的:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

        这里的顺序访问即迭代器的种类,可以从后往前遍历,也可以跳跃式遍历。

不要只使用具体类来编程、要优先使用抽象类和接口来编程


迭代器模式中的角色:

  • 迭代器角色(Iterator): 负责定义访问和遍历元素的接口。 
  • 具体迭代器角色(Concrete Iterator):实现迭代器接口,并要记录遍历中的当前位置。 
  • 容器角色(Container): 负责提供创建具体迭代器角色的接口。 
  • 具体容器角色(Concrete Container):实现创建具体迭代器角色的接口, 这个具体迭代器角色与该容器的结构相关。
迭代器接口:

最常用的就是 hasNext、next方法,前者判断是否存在下一个元素,后者用于获取该元素。

当然还有remove方法,但是在Java中,没有被使用的对象实例将会自动的被删除(GC)

public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}
具体的迭代器:

next方法是返回当前元素,并指向下一个元素。 

hasNext返回的是boolean,表示当前集合是否存在下一个元素,大概就是确认接下来是否可以调用next方法。

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;
    }
}
容器接口:
// 表示该方法只会生成一个用于遍历集合的迭代器
public interface Aggregate {
    public abstract Iterator iterator();
}
具体容器实现:

该数组的大小在实例化就被指定了,Iterator方法会生成并返回这个实例。当外部想遍历书架,就会调用这个方法。

public class BookShelf implements Aggregate{
    //容器中装着书
    private Book[] books;
    private int last = 0;

    public BookShelf(int maxsize) {
        this.books = new Book[maxsize];
    }

    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);
        //加this是该实例的构造方法要传入一个BookShelf的对象
    }
}
实体Book类:
public class Book {
    private String name;

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

    public String getName() {
        return name;
    }
}
Main:
public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(4);
        bookShelf.appendBook(new Book("one book"));
        bookShelf.appendBook(new Book("two book"));
        bookShelf.appendBook(new Book("three book"));
        bookShelf.appendBook(new Book("four book"));

        Iterator it = bookShelf.iterator();
        while(it.hasNext()){
            Book book = (Book)it.next();
            System.out.println(book.getName());
        }
    }
}
BookShelfIterator类发挥了Iterator的作用,构造函数会将集合实例保存在字段中,并初始index、
 Iterator it = bookShelf.iterator();

多态性: 运行期的代码返回的是实现Iterator接口的、而实现Iterator接口的构造方法中又传入了该集合实例、 编译期的代码本身就是写成接口形式。


实用:

上述迭代器实现的基本原理,在大部分集合中都有实现好了迭代器的用法,而且上述的容器用的是数组、那么就会存在满了越界的情况,解决办法就是每次添加前判断是否越界、扩容方案、直接用集合。

import java.util.ArrayList;
import java.util.Iterator;

public class test {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<String>();   // List接口实现了Iterable接口
        array.add("one book");
        array.add("two book");
        array.add("three book");
        array.add("four book");

        Iterator<String> iterator = array.iterator();

        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

注意了,前面的Iterator是我自己实现了,这里才是导入了Java自带的util包~~


练习~
import java.util.Iterator;

public class MyString implements Iterable<Character>{

    private int length;
    private String str;

    public MyString(String str) {
        this.str = str;
        this.length = str.length();
    }

    @Override
    public Iterator<Character> iterator() {

        class iter implements Iterator<Character>{

            private int cur = 0;

            @Override
            public boolean hasNext() {
                return cur < length ? true : false;
            }

            @Override
            public Character next() {
                Character c = str.charAt(cur);
                cur += 2;
                return c;
            }

        }
        return new iter();   //实现Iterabler的接口,返回迭代器
    }
    
}
// 自定义类的迭代,如跳跃取字符串字符
public class Main {

    public static void main(String[] args) {
        MyString str = new MyString("123456789");

        for(char c : str){
            System.out.print(c);
        }
    }
}

注~ 别忘了初衷,当时是看图的遍历用迭代器的形式来归纳一下、
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值