Java设计模式之行为型:迭代器模式

Java设计模式之行为型:迭代器模式

一、什么是迭代器模式:

        实际开发中,我们针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但我们不希望在集合容器的抽象接口层中充斥着各种不同的遍历操作,这时候我们就需要一种能完成下面功能的迭代器:

  • (1)遍历一个集合对象
  • (2)不需要了解聚合对象的内部结构
  • (3)提供多种不同的遍历方式

        迭代器模式提供一种访问集合中的各个元素,而不暴露其内部表示的方法。将在元素之间游走的职责交给迭代器,而不是集合对象,从而简化集合容器的实现,让集合容器专注于在它所应该专注的事情上,更加符合单一职责原则。
        

二、UML结构图:

Java设计模式之行为型:迭代器模式

  • Iterator:抽象迭代器,提供了在集合容器元素之间游走的方法。
  • ConcreteIterator:具体迭代器,能够对具体的集合容器进行遍历,每种集合容器都应该对应一个具体的迭代器
  • Aggregate:抽象容器类
  • ConcreteAggregate:具体容器类,实现 creatorIterator() 方法,返回该聚合对象的迭代器。

三、代码实现:

你项目组接到一个项目:对电视机的电视频道、电影菜单进行统一管理,建立一个统一的菜单管理界面,能够看到所有的电视界面、电影界面。你有三个手下:小李子、小杏子,他们分别就每个模块做开发工作,看他们都做了哪些工作。项目的UML结构图:

Java设计模式之行为型:迭代器模式

首先我们需要定义迭代器接口:Iterator.java

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

然后是两个具体的迭代器,一个迭代器遍历电视界面、一个迭代器遍历电影界面:

//电影节目的迭代器
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;
    }
}
//电视界面的迭代器
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 将电影解决添加到菜单项中
     */
    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 将电视频道节目添加菜单集合中
     */
    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();
    }
}

运行结果:

Java设计模式之行为型:迭代器模式

四、迭代器模式小结:

1、优点:

(1)迭代器模式简化了集合的接口,迭代子具备遍历功能,这样集合的接口就不需要重新实现遍历功能。

(2)每一个聚集对象都可以有一个或多个迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。因此,一个聚集对象可以同时有几个迭代在进行之中。

(3)由于遍历算法被封装在迭代子角色里面,因此迭代的算法可以独立于聚集角色变化。

(4)更好的封装性,访问一个集合对象的元素,无需暴露容器内部表示。

2、缺点:

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

(2)对于比较简单的遍历,使用迭代器模式显得较为繁琐,比如ArrayList直接就可以用for循环+get() 方法来遍历;

(3)抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如JDK内置迭代器Iterator就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类ListIterator等来实现,而ListIterator迭代器无法用于操作Set类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。

3、适用场景:

(1)访问一个集合对象的内容而无须暴露它的内部表示。

(2)需要为集合对象提供多种遍历方式。

(3)为遍历不同的聚合结构提供一个统一的接口。

PS:由于容器与迭代器的关系太密切了,所以大多数语言在实现容器的时候都给提供了迭代器,并且这些语言提供的容器和迭代器在绝大多数情况下就可以满足我们的需要,所以现在需要我们自己去实践迭代器模式的场景还是比较少见的,我们只需要使用语言中已有的容器和迭代器就可以了。


 设计模式系列文章:

Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)

Java设计模式之创建型:建造者模式

Java设计模式之创建型:单例模式

Java设计模式之创建型:原型模式

Java设计模式之结构型:适配器模式

Java设计模式之结构型:装饰器模式

Java设计模式之结构型:代理模式

Java设计模式之结构型:桥接模式

Java设计模式之结构型:外观模式

Java设计模式之结构型:组合模式

Java设计模式之结构型:享元模式

Java设计模式之行为型:策略模式

Java设计模式之行为型:模板方法模式

Java设计模式之行为型:责任链模式

Java设计模式之行为型:观察者模式

Java设计模式之行为型:访问者模式

Java设计模式之行为型:中介者模式

Java设计模式之行为型:命令模式

Java设计模式之行为型:状态模式

Java设计模式之行为型:备忘录模式

Java设计模式之行为型:迭代器模式

Java设计模式之行为型:解释器模式


原博客链接:设计模式读书笔记—–迭代器模式_chenssy 的技术博客-CSDN博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114642.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java多线程设计模式:wait/notify机制

    Java多线程设计模式:wait/notify机制

    2021年5月6日
  • java工厂模式实例(设计模式)「建议收藏」

    java工厂模式实例(设计模式)「建议收藏」java工厂模式开篇声明,此理解为作者自身理解,不一定正确,如有错误请大佬们指正。工厂模式,在作者看来,从现实生活来说,就是一个工厂,里面有N个车间,每个车间会生产不同的产品,而租户只需要告诉这个工厂的老板我需要一个什么产品,老板会去找到对应的车间返回给租户使用。画个图理解:如果使用java语言来描述则是,对具有相同动作,不同动作执行过程的一类方法抽象出一个接口类,然后不同的实现类对接口类中的接口进行不同的实现,并且编写一个工厂类,根据传入获取不同的实现类实例返回给调用者

    2022年7月20日
  • java设计模式3,里氏替换原则

    java设计模式3,里氏替换原则里氏替换原则的内容可以描述为:“派生类(子类)对象可以在程序中代替其基类(超类)对象。”

    2022年10月29日
  • 十五、组合模式—— 容器与内容的一致性 #和设计模式一起旅行#

    组合具有一致性…故事背景坚持去输出真的很不容易,今天的的天气真的是热啊!我之前一直想些一个系列是和设计模式去旅行,通过构思一些场景,让自己更好的理解和表达设计模式,但是有时候为了思考一个适合的故事会花费很多时间,so,从这里开始,如果后面的设计模式想到了好的场景的话就写故事背景,要不就简单介绍,重点看故事主角。在现实生活中很多地方我们会使用到树形结构,在软件中也随处可见,例…

    2022年2月27日
  • PHP设计模式-工厂模式[通俗易懂]

    PHP设计模式-工厂模式[通俗易懂]PHP设计模式-工厂模式一、工厂模式概念工厂模式,顾名思义,像工厂的流水线,固定的规格,固定的材料,做固定的事情。工厂模式分为三种:简单工厂、工厂方法、抽象工厂,三种工厂的区别是,抽象工厂由多条产品线,而工厂方法只有一条产品线,是抽象工厂的简化。而工厂方法和简单工厂相对,大家初看起来好像工厂方法增加了许多代码但是实现的功能和简单工厂一样。但本质是,简单工厂并未严格遵循设计模式的开闭原则,当需要增加新产品时也需要修改工厂代码。但是工厂方法则严格遵守开闭原则,模式只负责抽象工厂接口,具体工厂交给客.

    2022年7月25日
  • 设计模式之抽象工厂模式代码示例

    设计模式之抽象工厂模式代码示例

    2021年7月9日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号