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博客

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 23种设计模式汇总整理

    设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式结构型模式,共七种:适配器模式、装饰者模式、代理模式、外观模式、桥接模式、组合模式、享元模式。行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。其实还有两类:并发型模式和线程池模式。…

  • 十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#

    不在其位,不谋其政! –出自《论语·泰伯》故事背景在现实世界中,有很多情况下会遇到一些推卸责任的场景,比如要办理一件事的时候,被告诉你要去做个做这个事情,但是去了这个地方,确告诉要到另一个地方去,最后搞了很久,才办完这一件事。这种情况下,就可以简单的称为踢皮球,也就是推卸责任。在软件中,当外部请求程序进行某个出来,这个程序无法处理就把该请求转给其他对象负责,当对个对象组…

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

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

  • Java常用设计模式

    Java常用设计模式一、设计模式概念1、定义​Java包含23种设计模式,是一套对代码设计经验的总结,被人们反复利用,多人熟知的代码设计方式。2、目的​为了提高代码的可读性,可扩展性以及代码的复用性,为了解决在写代码过程中遇到的代码设计问题。3、设计模式的六大原则​3.1开闭原则​对扩展开放,对修改关闭(尽可能对代码少修改)​3.2里氏替换原则​它是面向对象基本原则之一,任何父类(基类)出现的地方,子类都可以出现,也就是子类可以替换父类的任何功能(体现了父类的可扩展性)3.3依赖

  • 设计模式之建造者模式

    设计模式之建造者模式

    2021年12月16日
  • GOF23—工厂设计模式练习代码和随笔

    GOF23—工厂设计模式练习代码和随笔

发表回复

您的电子邮箱地址不会被公开。

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