zoukankan      html  css  js  c++  java
  • 行为型模式:迭代器模式

    LieBrother原文
    行为型模式:迭代器模式

    景

    十一大行为型模式之六:迭代器模式。

    简介

    姓名 :迭代器模式

    英文名 :Iterator Pattern

    价值观 :人生没有回头路

    个人介绍

    Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
    它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
    (来自《设计模式之禅》)

    你要的故事

    大家伙听歌频率高么?是不是经常听歌曲来放松心情?我是经常会听歌,心情不好的时候听歌,心情好的时候也听歌。。。今天讲的迭代器模式,我们就拿听歌这件事来说说,大家都知道听歌有几种模式:单曲循环、列表循环、随机等等。。。现在网易云音乐还多了一个心动模式。

    既然说到迭代器模式,那这里就要着重讲讲列表循环这个听歌模式,其他的就先抛到脑后。在列表循环中,歌曲从第一条播放到最后一条,也就是一个遍历歌单的过程。我们有 2 种实现方式,一种是没有迭代器,通过获取歌单,用 for 循环遍历每一个歌曲,然后播放;另外一种是使用迭代器,获取歌单的一个迭代器,通过迭代器来遍历每一个歌曲,然后播放。下面我们就用代码来实现这 2 种方式。

    木有迭代器

    public class NoIteratorTest {
    
        public static void main(String[] args) {
            NetEaseMusic1 netEaseMusic1 = new NetEaseMusic1();
            netEaseMusic1.listenToMusicByLoop();
        }
    }
    
    /**
     * 网易云音乐
     */
    class NetEaseMusic1 {
    
        private IList1 songList;
    
        public NetEaseMusic1() {
            songList = new SongList1(3);
            songList.add(new Song("让我留在你身边", "陈奕迅"));
            songList.add(new Song("你曾是少年", "SHE"));
            songList.add(new Song("Perfect", "Ed Sheeran"));
        }
    
        /**
         * 列表循环
         */
        public void listenToMusicByLoop() {
            for (int i = 0; i < songList.size(); i++) {
                System.out.println("听歌:" + ((ISong)songList.get(i)).getSongInfo());
            }
        }
    
    }
    
    /**
     * 容器接口
     */
    interface IList1 {
    
        void add(Object object);
    
        Object get(int index);
    
        int size();
    }
    
    /**
     * 歌单
     */
    class SongList1 implements IList1 {
    
        private ISong[] songs;
        private int index;
        private int size;
    
        public SongList1(int size) {
            songs = new ISong[size];
            index = 0;
            size = 0;
        }
    
        @Override
        public void add(Object object) {
            songs[index++] = (ISong) object;
            size ++;
        }
    
        @Override
        public Object get(int index) {
            if (index < size) {
                return songs[index];
            }
            return null;
        }
    
        @Override
        public int size() {
            return size;
        }
    }
    
    
    /**
     * 歌曲接口
     */
    interface ISong {
        String getSongInfo();
    }
    
    /**
     * 歌曲
     */
    class Song implements ISong{
    
        private String name;
        private String singer;
    
        public Song(String name, String singer) {
            this.name = name;
            this.singer = singer;
        }
    
        @Override
        public String getSongInfo() {
            return this.name + "--" + this.singer;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSinger() {
            return singer;
        }
    
        public void setSinger(String singer) {
            this.singer = singer;
        }
    
    }
    
    打印结果:
    听歌:让我留在你身边--陈奕迅
    听歌:你曾是少年--SHE
    听歌:Perfect--Ed Sheeran
    

    我们定义了 ISong 接口,里面有个 getSongInfo() 方法来获取歌曲信息,用 Song 类来定义歌曲。没有用 Java 自带的容器来存放歌曲,这里实现了一个自定义容器接口 IList1,定义 SongList1 来做歌曲的容器,为什么不用 Java 自带的 ArrayList 等等?因为 Java 自带的已经实现了迭代器功能了,我们这里自定义其实就是在模仿自带的容器的实现。NetEaseMusic1 类是充当网易云音乐客户端,在 listenToMusicByLoop() 方法中,我们可以看到是获取了歌单 songList,然后一个一个遍历,这是没有使用迭代器的代码。

    下面看一下使用迭代器的代码是怎么样的。

    用迭代器实现遍历

    public class IteratorTest {
    
        public static void main(String[] args) {
            NetEaseMusic2 netEaseMusic2 = new NetEaseMusic2();
            netEaseMusic2.listenToMusicByLoop();
        }
    
    }
    
    /**
     * 网易云音乐
     */
    class NetEaseMusic2{
    
        private IList2 songList;
    
        public NetEaseMusic2() {
            songList = new SongList2(3);
            songList.add(new Song("让我留在你身边", "陈奕迅"));
            songList.add(new Song("你曾是少年", "SHE"));
            songList.add(new Song("Perfect", "Ed Sheeran"));
        }
    
        /**
         * 列表循环
         */
        public void listenToMusicByLoop() {
            IIterator iterator = songList.iterator();
            while (iterator.hasNext()) {
                System.out.println("听歌:" + ((ISong)iterator.next()).getSongInfo());
            }
    
        }
    
    }
    
    /**
     * 容器接口
     */
    interface IList2 {
    
        IIterator iterator();
    
        void add(Object object);
    
        Object get(int index);
    
        int size();
    }
    
    /**
     * 歌单
     */
    class SongList2 implements IList2 {
    
        private ISong[] songs;
        private int index;
        private int size;
    
        public SongList2(int size) {
            songs = new ISong[size];
            index = 0;
            size = 0;
        }
    
        @Override
        public IIterator iterator() {
            return new IteratorImpl(this);
        }
    
        @Override
        public void add(Object object) {
            songs[index++] = (ISong) object;
            size ++;
        }
    
        @Override
        public Object get(int index) {
            if (index < size) {
                return songs[index];
            }
            return null;
        }
    
        @Override
        public int size() {
            return size;
        }
    }
    
    
    /**
     * 迭代器
     */
    interface IIterator {
        Object next();
        boolean hasNext();
    }
    
    /**
     * 迭代器实现类
     */
    class IteratorImpl implements IIterator {
    
        private IList2 list;
        private int index;
    
        public IteratorImpl(IList2 list) {
            this.list = list;
            this.index = 0;
        }
    
        @Override
        public Object next() {
            return list.get(index++);
        }
    
        @Override
        public boolean hasNext() {
            if (index < list.size()) {
                return true;
            }
            return false;
        }
    }
    
    打印结果:
    听歌:让我留在你身边--陈奕迅
    听歌:你曾是少年--SHE
    听歌:Perfect--Ed Sheeran
    

    代码中我们自定义了一个迭代器接口 IIterator 和迭代器具体实现类 IteratorImpl,有关键的 2 个方法,hasNext() 判断是否有存在下一个元素,next() 获取下一个元素。而 IList2 接口则比 IList1 接口多了一个获取迭代器的方法 iterator(),这让网易云音乐在遍历歌单的时候,不用直接使用 songList 来遍历,而可以通过 songList.iterator() 获取迭代器来实现遍历的过程。NetEaseMusic2.listenToMusicByLoop() 这个方法里面就直接获取迭代器来遍历了。

    代码:
    Iterator Pattern

    总结

    迭代器模式是所有设计模式中使用最广泛的,有不少开发同学知道迭代器,但是不知道它是设计模式的。虽然迭代器的代码会比没有迭代器的代码复杂,但是加上迭代器可以让容器有统一的遍历代码风格,不用各自去实现遍历方法,有更好的封装性。在 Java 中,迭代器已经运用很广泛,比如 Java 中访问 MySQL 获取数据就是用迭代器来遍历数据的。好了,迭代器模式就讲到这,大家知道的知识就不多说啦。

    参考资料:《大话设计模式》、《设计模式之禅》

    推荐阅读:

    行为型模式:策略模式

    行为型模式:责任链模式

    行为型模式:命令模式

    希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号:LieBrother,第一时间获取文章推送阅读,也可以一起交流,交个朋友。

    公众号

  • 相关阅读:
    python读取csv数据(添加列名,指定分隔方式)
    loc_survived
    数据预处理
    hadoop 指令
    pd.concat
    DataFrame
    SQL左连接
    mysql mysql之把查询的结果保存到新表(小知识点)
    啦啦啦啦 mysql 授权
    ArrayList和LinkedList的区别以及优缺点
  • 原文地址:https://www.cnblogs.com/liebrother/p/10448349.html
Copyright © 2011-2022 走看看