为了账号安全,请及时绑定邮箱和手机立即绑定

设计模式经典-迭代器模式

定义:

迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

模式的使用场景

 Java JDK 1.2 版开始支持迭代器。每一个迭代器提供next()以及hasNext()方法,同时也支持remove()(1.8的时候remove已经成为default throw new UnsupportedOperationException("remove"))。对Android来说,集合Collection实现了Iterable接口,就是说,无论是List的一大家子还是Map的一大家子,我们都可以使用Iterator来遍历里面的元素

uml图:

 这里写图片描述

角色:

1.迭代器接口Iterator:该接口必须定义实现迭代功能的最小定义方法集比如提供hasNext()和next()方法。

2.迭代器实现类:迭代器接口Iterator的实现类。可以根据具体情况加以实现。

3.容器接口:定义基本功能以及提供类似Iterator iterator()的方法。

4.容器实现类:容器接口的实现类。必须实现Iterator iterator()4.法。

具体实例:
首先我们需要定义迭代器接口。Iterator.java
public interface Iterator {
    boolean hasNext();
    Object next();
}
然后是我们两个具体的迭代器。一个迭代器遍历电视界面、一个迭代器遍历电影界面。
电影节目的迭代器:FilmMenuIterator.java
public class FilmMenuIterator implements Iterator{
    MenuItem[] menuItems;
    int position = 0;

    public FilmMenuIterator(MenuItem[] menuItems){
        this.menuItems = menuItems;
    }

    public boolean hasNext() {
        if(position > menuItems.length-1  menuItems[position] == null){
            return false;
        }
        return true;
    }

    public Object next() {
        MenuItem menuItem = menuItems[position];
        position ++;
        return menuItem;
    }

}
电视界面的迭代器:TVChanneMenuIterator.java
public class TVChanneMenuIterator implements Iterator{

    List<MenuItem> menuItems;
    int position = 0;

    public TVChanneMenuIterator(List<MenuItem> menuItems){
        this.menuItems = menuItems;
    }

    public boolean hasNext() {
        if(position > menuItems.size()-1  menuItems.get(position) == null){
            return false;
        }
        else{
            return true;
        }
    }

    public Object next() {
        MenuItem menuItem = menuItems.get(position);
        position ++;
        return menuItem;
    }
}
然后是菜单接口,该接口提供返回具体迭代器的方法:
createIterator()。
public interface TelevisionMenu {
    public void addItem(int channe,String name,String description);
    public Iterator createIrerator();
}
两个具体聚合类。这个两个聚合类实现createIterator()方法,分别返回电视界面的聚合类和电影界面的聚合类。
public class FilmMenu implements TelevisionMenu{
    static final int MAX_ITEMS = 5;    //菜单最大长度
    MenuItem[] menuItems;
    int numberOfItems = 0;

    /**
     * 构造函数完成初始化
     */
    public FilmMenu(){
        menuItems = new MenuItem[MAX_ITEMS];

        addItem(1, "绝世天劫", "这是布鲁斯威利斯主演的...");
        addItem(2, "达芬奇密码", "这是我最喜欢的电影之一...");
        addItem(3, "黑客帝国123", "不知道你能够看懂不???");
        addItem(4, "我的女友是机器人", "一部我不反感的经典爱情电影...");
        addItem(5, "肖申克的救赎", "自由,幸福,离你有多远");
    }

    /**
     * @desc 将电影解决添加到菜单项中
     * @param channe
     * @param name
     * @param description
     * @return void
     */
    public void addItem(int channe,String name,String description){
        MenuItem tvmenuiItem = new MenuItem(channe, name, description);
        //判断数组是否越界
        if(numberOfItems > MAX_ITEMS){
            System.out.println("不好意思,菜单满了....");
        }
        else{
            menuItems[numberOfItems] = tvmenuiItem;
            numberOfItems ++;
        }
    }

    public Iterator createIrerator() {
        return new FilmMenuIterator(menuItems);
    }

}
public class TVChanneMenu implements TelevisionMenu{
    List<MenuItem> menuItems;

    /**
     * 构造函数完成初始化
     */
    public TVChanneMenu(){
        menuItems = new ArrayList<MenuItem>();
        addItem(1, "CCTV-1", "This is CCTV-1");
        addItem(2, "CCTV-2", "This is CCTV-2");
        addItem(3, "CCTV-3", "This is CCTV-3");
        addItem(4, "CCTV-4", "This is CCTV-4");
        addItem(5, "CCTV-5", "This is CCTV-5");
    }

    /**
     * @desc 将电视频道节目添加菜单集合中
     * @param channe  频道
     * @param name  名称
     * @param description  描述
     * @return void
     */
    public void addItem(int channe,String name,String description){
        MenuItem tvMenuItem = new MenuItem(channe, name, description);
        menuItems.add(tvMenuItem);
    }

    public Iterator createIrerator() {
        return new TVChanneMenuIterator(menuItems);
    }

}
终于完成了,现在就可以来实现主菜单了,用来展示、遍历所有的电视、电影界面咯。
public class MainMenu {
    TelevisionMenu tvMenu;
    FilmMenu filmMenu;

    public MainMenu(TelevisionMenu tvMenu,FilmMenu filmMenu){
        this.tvMenu = tvMenu;
        this.filmMenu  = filmMenu;
    }

    public void printMenu(){
        Iterator tvIterator = tvMenu.createIrerator();
        Iterator filmIterator = filmMenu.createIrerator();

        System.out.println("电视节目有:");
        printMenu(tvIterator);
        System.out.println("----------------------------------------------------------------");
        System.out.println("电影节目有:");
        printMenu(filmIterator);
    }

    private void printMenu(Iterator iterator) {
        while(iterator.hasNext()){
            MenuItem menuItem = (MenuItem) iterator.next();
            System.out.print("channe:"+menuItem.getChanne()+",  ");
            System.out.print("name:"+menuItem.getName()+",  ");
            System.out.println("description :"+menuItem.getDescription());
        }
    }
}
测试程序:
public class Test {
    public static void main(String[] args) {
        TVChanneMenu tvMenu = new TVChanneMenu();
        FilmMenu filmMenu = new FilmMenu();

        MainMenu mainMenu = new MainMenu(tvMenu, filmMenu);
        mainMenu.printMenu();
    }
}
运行结果
这里写图片描述
优点:

1、它支持以不同的方式遍历一个聚合对象。

2、迭代器简化了聚合类。

3、在同一个聚合上可以有多个遍历。

4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点

由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

模式总结

1、迭代器模式提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示。

2、将遍历聚合对象中数据的行为提取出来,封装到一个迭代器中,通过专门的迭代器来遍历聚合对象的内部数据,这就是迭代器模式的本质。迭代器模式是“单一职责原则”的完美体现。

3、当使用迭代器的时候,我们依赖聚合提供遍历。

4、迭代器提供了一个通用的接口,让我们遍历聚合的项,放我们编码使用聚合项时,就可以使用多态机制。

我的微信号:rdst6029930

欢迎交流

点击查看更多内容
11人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
424
获赞与收藏
5663

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消