您的设计模式——迭代器模式【Iterator Pattern】

周五下午,我正在看技术网站,第六感官发觉有人在身后,扭头一看,我 C,老大站在背后,赶忙站起来,
“王经理,你找我?” 我说。“哦,在看技术呀。有个事情找你谈一下,你到我办公室来一下。” 老大说。
到老大办公室,“是这样,刚刚我在看季报,我们每个项目的支出费用都很高,项目情况复杂,人员情况也不简单,我看着也有点糊涂,你看,这是我们现在还在开发或者维护的 103 个项目,你能不能先把这些项目信息重新打印一份给我,咱们好查查到底有什么问题。”老大说。“这个好办,我马上去办”我爽快的答复道。很快我设计了一个类图,并开始实施:

这里写图片描述

类图非常简单,是个程序员都能实现,我们来看看简单的东西:

package com.alex.patterns.iterator;

/**
 * @author Alex
 * 定义一个接口,所有的项目都是一个接口
 */
public interface IProject {
    // 从老板这里看到的就是项目信息
    public String getProjectInfo();
}

定义了一个接口,面向接口编程嘛,当然要定义接口了,然后看看实现类:

package com.alex.patterns.iterator;

/**
 * @author Alex
 * 所有项目的信息类
 */
public class Project implements IProject {
    // 项目名称
    private String name = "";
    // 项目成员数量
    private int num = 0;
    // 项目费用
    private int cost = 0;

    // 定义一个构造函数,把所有老板需要看到的信息存储起来
    public Project(String name, int num, int cost) {
        // 赋值到类的成员变量中
        this.name = name;
        this.num = num;
        this.cost = cost;
    }

    // 得到项目的信息
    public String getProjectInfo() {
        String info = "";
        // 获得项目的名称
        info = info + "项目名称是:" + this.name;
        // 获得项目人数
        info = info + "\t项目人数: " + this.num;
        // 项目费用
        info = info + "\t 项目费用:" + this.cost;
        return info;
    }
}

实现类也是比较简单的,通过构造函数传递过来要显示的数据,然后放到 getProjectInfo 中显示,这太
easy 了!,然后我们老大要看看结果了:

package com.alex.patterns.iterator;

import java.util.ArrayList;

/**
 * @author Alex
 * 老板来看项目信息了
 */
public class Boss {
    public static void main(String[] args) {
        // 定义一个List,存放所有的项目对象
        ArrayList<IProject> projectList = new ArrayList<IProject>();
        // 增加星球大战项目
        projectList.add(new Project("星球大战项目", 10, 100000));
        // 增加扭转时空项目
        projectList.add(new Project("扭转时空项目", 100, 10000000));
        // 增加超人改造项目
        projectList.add(new Project("超人改造项目", 10000, 1000000000));
        // 这边100个项目
        for (int i = 4; i < 104; i++) {
            projectList.add(new Project("第" + i + "个项目", i * 5, i * 1000000));
        }
        // 遍历一下ArrayList,把所有的数据都取出
        for (IProject project : projectList) {
            System.out.println(project.getProjectInfo());
        }
    }
}

老大一看,非常 Happy,这么快就出结果了,大大的把我夸奖了一番,然后就去埋头去研究那堆枯燥的报
表了,然后我回到座位上,又看了一遍程序(心里很乐,就又想看看自己的成果),想想了,应该还有另外一种
实现方式,因为是遍历嘛,让我想到的就是迭代器模式,我先把类图画出来:

这里写图片描述

看着是不是复杂了很多?是的,是有点复杂了,这个我等会说明原因,我们看代码实现,先 IProject 1接
口:

package com.alex.patterns.iterator;

/**
 * @author Alex
 * 定义一个接口,所有的项目都是一个接口
 */
public interface IProject1 {
    // 增加项目
    public void add(String name, int num, int cost);

    // 从老板这里看到的就是项目信息
    public String getProjectInfo();

    // 获得一个可以被遍历的对象
    public IProjectIterator iterator();
}

这里多了两个方法,一个是 add 方法,这个方法是增加项目,也就是说产生了一个对象后,直接使用 add
方法增加项目信息。我们再来看实现类:

package com.alex.patterns.iterator;

import java.util.ArrayList;

/**
 * @author Alex
 * 所有项目的信息类
 */
@SuppressWarnings("all")
public class Project1 implements IProject1 {
    // 定义一个项目列表,说有的项目都放在这里
    private ArrayList<IProject> projectList = new ArrayList<IProject>();
    // 项目名称
    private String name = "";
    // 项目成员数量
    private int num = 0;
    // 项目费用
    private int cost = 0;

    public Project1() {
    }

    // 定义一个构造函数,把所有老板需要看到的信息存储起来
    private Project1(String name, int num, int cost) {
        // 赋值到类的成员变量中
        this.name = name;
        this.num = num;
        this.cost = cost;
    }

    // 增加项目
    public void add(String name, int num, int cost) {
        this.projectList.add(new Project(name, num, cost));
    }

    // 得到项目的信息
    public String getProjectInfo() {
        String info = "";
        // 获得项目的名称
        info = info + "项目名称是:" + this.name;
        // 获得项目人数
        info = info + "\t项目人数: " + this.num;
        // 项目费用
        info = info + "\t 项目费用:" + this.cost;
        return info;
    }

    // 产生一个遍历对象
    public IProjectIterator iterator() {
        return new ProjectIterator(this.projectList);
    }
}

项目信息类已经产生,我们再来看看我们的迭代器是如何实现的,先看接口:

package com.alex.patterns.iterator;

import java.util.Iterator;

/**
 * @author Alex
 * 定义个Iterator接口
 */
@SuppressWarnings("all")
public interface IProjectIterator extends Iterator {
}

大家可能很奇怪,你定义的这个接口方法、变量都没有,有什么意义呢?有意义,所有的 Java 书上都一直
说是面向接口编程, 你的接口是对一个事物的描述, 也就是说我通过接口就知道这个事物有哪些方法, 哪些属性,
我们这里的 IProjectIterator 是要建立一个指向 Project 类的迭代器,目前暂时定义的就是一个通用的迭
代器, 可能以后会增加 IProjectIterator 的一些属性或者方法。 当然了, 你也可以在实现类上实现两个接口,
一个是 Iterator,一个是 IProjectIterator(这时候,这个接口就不用继承 Iterator),杀猪杀尾巴,
各有各的杀发。我的习惯是:如果我要实现一个容器或者其他 API 提供接口时,我一般都自己先写一个接口继
承, 然后再继承自己写的接口, 保证自己的实现类只用实现自己写的接口 (接口传递, 当然也要实现顶层的接口) ,
程序阅读也清晰一些。我们继续看迭代器的实现类:

package com.alex.patterns.iterator;

import java.util.ArrayList;

/**
 * @author Alex
 * 定义一个迭代器
 */
public class ProjectIterator implements IProjectIterator {
    // 所有的项目都放在这里ArrayList中
    private ArrayList<IProject> projectList = new ArrayList<IProject>();
    private int currentItem = 0;

    // 构造函数传入projectList
    public ProjectIterator(ArrayList<IProject> projectList) {
        this.projectList = projectList;
    }

    // 判断是否还有元素,必须实现
    public boolean hasNext() {
        // 定义一个返回值
        boolean b = true;
        if (this.currentItem >= projectList.size() || this.projectList.get(this.currentItem) == null) {
            b = false;
        }
        return b;
    }

    // 取得下一个值
    public IProject next() {
        return (IProject) this.projectList.get(this.currentItem++);
    }

    // 删除一个对象
    public void remove() {
        // 暂时没有使用到
    }
}

都写完毕了,然后看看我们的 Boss 类有多少改动:

package com.alex.patterns.iterator;

/**
 * @author Alex
 * 老板来看项目信息了
 */
public class Boss1 {
    public static void main(String[] args) {
        // 定义一个List,存放所有的项目对象
        IProject1 project = new Project1();
        // 增加星球大战项目
        project.add("星球大战项目ddddd", 10, 100000);
        // 增加扭转时空项目
        project.add("扭转时空项目", 100, 10000000);
        // 增加超人改造项目
        project.add("超人改造项目", 10000, 1000000000);
        // 这边100个项目
        for (int i = 4; i < 104; i++) {
            project.add("第" + i + "个项目", i * 5, i * 1000000);
        }
        // 遍历一下ArrayList,把所有的数据都取出
        IProjectIterator projectIterator = project.iterator();
        while (projectIterator.hasNext()) {
            IProject p = (IProject) projectIterator.next();
            System.out.println(p.getProjectInfo());
        }
    }
}

上面的程序增加了复杂性,但是从面向对象的开发上来看,project.add()增加一个项目是不是更友好一
些?
上面的例子就使用了迭代器模式,我们来看看迭代器的通用类图:

这里写图片描述

类图是很简单,但是你看用起来就很麻烦,就比如上面例子的两个实现方法,你觉的那个简单?当然是第一
个了!23 个设计模式是为了简化我们代码和设计的复杂度、耦合程度,为什么我们用了这个迭代器模式程序会复杂了一些呢?这是为什么?因为从 JDK 1.2 版本开始增加 java.util.Iterator 这个接口,并逐步把
Iterator 应用到各个聚集类(Collection)中,我们来看 JDK 1.5 的 API 帮助文件,你会看到有一个叫
java.util.Iterable 的接口,看看有多少个接口继承了它:

这里写图片描述

java.util.Iterable 接口只有一个方法:iterator(),也就说通过 iterator()这个方法去遍历聚
集类中的所有方法或属性,基本上现在所有的高级的语言都有 Iterator 这个接口或者实现,Java 已经把迭代
器给我们准备了,我们再去写迭代器,是不是“六指儿抓痒,多一道子”?所以呀,这个迭代器模式也有点没落
了,基本上很少有项目再独立写迭代器了,直接使用 List 或者 Map 就可以完整的解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值