← 返回首页
设计模式基础教程(二十六)
发表时间:2021-08-28 11:53:51
迭代器模式

1.迭代器模式

迭代器模式(Iterator Pattern) :提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor)。迭代器模式是一种对象行为型模式。

在迭代器模式中,提供一个外部的迭代器来对聚合对象进行访问和遍历,迭代器定义了一个访问该聚合元素的接口,并且可以跟踪当前遍历的元素,了解哪些元素已经遍历过而哪些没有。

有了迭代器模式,我们会发现对一个复杂的聚合对象的操作会变得如此简单。

迭代器模式包含如下角色: - Iterator: 抽象迭代器 - ConcreteIterator: 具体迭代器 - Aggregate: 抽象聚合类 - ConcreteAggregate: 具体聚合类

聚合是一个管理和组织数据对象的数据结构。 聚合对象主要拥有两个职责:一是存储内部数据;二是遍历内部数据。 存储数据是聚合对象最基本的职责。 将遍历聚合对象中数据的行为提取出来,封装到一个迭代器中,通过专门的迭代器来遍历聚合对象的内部数据,这就是迭代器模式的本质。迭代器模式是“单一职责原则”的完美体现。

2.实例

电视机遥控器就是一个迭代器的实例,通过它可以实现对电视机频道集合的遍历操作,本实例我们将模拟电视机遥控器的实现。

项目结构图如下:

设计电视迭代器接口

public interface TVIterator {
    void setChannel(int channel);
    boolean isFirst();
    boolean isLast();
    void previous();
    void next();
    Object currentChannel();
}

设计电视机抽象类

public abstract class Television {
    public abstract TVIterator  createIterator();
}

创维电视机类

public class SkyworthTelevision extends Television {

    private Object[] objs={"CCTV-1","CCTV-2","CCTV-3","CCTV-4","CCTV-5","CCTV-6","CCTV-7","CCTV-8"};
    @Override
    public TVIterator createIterator() {
        // TODO Auto-generated method stub
        return new SkyworthIterator();
    }

    private class SkyworthIterator implements TVIterator{

        private int currentIndex=0;
        @Override
        public void setChannel(int channel) {
            this.currentIndex=channel;
        }

        @Override
        public boolean isFirst() {
            // TODO Auto-generated method stub
            return currentIndex==0;
        }

        @Override
        public boolean isLast() {
            // TODO Auto-generated method stub
            return currentIndex==objs.length;
        }

        @Override
        public void previous() {
            if(currentIndex>0){
                currentIndex--;
            }
        }

        @Override
        public void next() {
            if(currentIndex<objs.length){
                currentIndex++;
            }
        }

        @Override
        public Object currentChannel() {
            // TODO Auto-generated method stub
            return objs[currentIndex];
        }
    }
}

TCL电视机类

public class TCLTelevision extends Television {
    private Object[] objs = {"湖南卫视", "北京卫视", "上海卫视", "湖北卫视", "黑龙江卫视"};
    @Override
    public TVIterator createIterator() {
        // TODO Auto-generated method stub
        return new TCLIterator();
    }
    class TCLIterator implements TVIterator {
        private int currentIndex = 0;
        public void next() {
            if (currentIndex < objs.length) {
                currentIndex++;
            }
        }
        public void previous() {
            if (currentIndex > 0) {
                currentIndex--;
            }
        }
        public void setChannel(int i) {
            currentIndex = i;
        }
        public Object currentChannel() {
            return objs[currentIndex];
        }
        public boolean isLast() {
            return currentIndex == objs.length;
        }
        public boolean isFirst() {
            return currentIndex == 0;
        }
    }
}

XML解析工具类

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class XMLUtil {
    //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
    public static Object getBean() {
        try {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(XMLUtil.class.getClassLoader().getResourceAsStream("config.xml"));
            //获取包含类名的文本节点
            NodeList nl = doc.getElementsByTagName("className");
            String className = nl.item(0).getTextContent();
            //通过类名生成实例对象并将其返回
            Class c = Class.forName(className);
            Object obj = c.newInstance();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

配置文档

<?xml version="1.0"?>
<config>
     <className>com.simoniu.domain.SkyworthTelevision</className>
</config>

测试类

public class TestIteratorDemo01 {

    public static void main(String[] args) {
        Television television = (Television) XMLUtil.getBean();
        display(television);
        System.out.println("============");
        reverseDisplay(television);
    }

    private static void reverseDisplay(Television television) {
        TVIterator iterator = television.createIterator();
        iterator.setChannel(5);
        System.out.println("逆序遍历电视频道:");
        while (!iterator.isFirst()) {
            iterator.previous();
            System.out.println(iterator.currentChannel().toString());
        }
    }

    private static void display(Television television) {
        TVIterator iterator = television.createIterator();
        System.out.println("电视机频道:");
        while (!iterator.isLast()) {
            System.out.println(iterator.currentChannel().toString());
            iterator.next();
        }
    }
}

运行结果:
电视机频道:
CCTV-1
CCTV-2
CCTV-3
CCTV-4
CCTV-5
CCTV-6
CCTV-7
CCTV-8
============
逆序遍历电视频道:
CCTV-5
CCTV-4
CCTV-3
CCTV-2
CCTV-1