前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java设计模式之迭代器模式

Java设计模式之迭代器模式

作者头像
CoderJed
发布2018-11-09 15:05:07
7610
发布2018-11-09 15:05:07
举报
文章被收录于专栏:Jed的技术阶梯

老板让我打印各个项目的报表,包括项目名称,人数,开销等信息,这个好办,看下面的类图:

image.png

然后是上面类图的代码实现,非常简单:

代码语言:javascript
复制
public interface IProject {
    
    String getProjectInfo();

}
代码语言:javascript
复制
public class Project implements IProject {
    
    private String name; // 项目名称
    private int num; // 项目人数
    private int cost; // 项目支出
    
    public Project(String name, int num, int cost) {
        this.name = name;
        this.num = num;
        this.cost = cost;
    }
    
    
    @Override
    public String getProjectInfo() {
        StringBuilder builder = new StringBuilder();
        builder.append("项目名称:").append(name).append(",项目人数:").append(num).append(",项目支出:").append(cost);
        return builder.toString();
    }

}

Boss想查看各项目明细,需要这么做:

代码语言:javascript
复制
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, 1000000));
        // 增加超人改造项目
        projectList.add(new Project("超人改造", 10000, 10000000));
        // 增加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());
        }

    }

}

# 运行结果
项目名称:星球大战,项目人数:10,项目支出:100000
项目名称:扭转时空,项目人数:100,项目支出:1000000
项目名称:超人改造,项目人数:10000,项目支出:10000000
项目名称:第4个项目,项目人数:20,项目支出:4000000
......

我开始思考,在这种场景下,使用迭代器模式会更好,于是我修改了类图:

然后根据类图修改了代码:

代码语言:javascript
复制
public interface IProject {
    
    // 增加项目
    void add(String name, int num, int cost);
    
    // 获得项目信息
    String getProjectInfo();
    
    // 获得一个可以被遍历的对象
    IProjectIterator iterator();

}
代码语言:javascript
复制
public class Project implements IProject {
    
    private List<IProject> projectList = new ArrayList<>(); // 项目列表
    private String name; // 项目名称
    private int num; // 项目人数
    private int cost; // 项目支出
    
    public Project() {}
    
    private Project(String name, int num, int cost) {
        this.name = name;
        this.num = num;
        this.cost = cost;
    }
    
    @Override
    public void add(String name, int num, int cost) {
        this.projectList.add(new Project(name, num, cost));
    }
    
    @Override
    public String getProjectInfo() {
        StringBuilder builder = new StringBuilder();
        builder.append("项目名称:").append(name).append(",项目人数:").append(num).append(",项目支出:").append(cost);
        return builder.toString();
    }

    @Override
    public IProjectIterator iterator() {
        return new ProjectIterator(projectList);
    }

}
代码语言:javascript
复制
public interface IProjectIterator extends Iterator<IProject> {

}

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

代码语言:javascript
复制
public class ProjectIterator implements IProjectIterator {
    
    // 项目列表
    private List<IProject> projectList = new ArrayList<>();
    private int currentItem = 0;
    
    public ProjectIterator(List<IProject> projectList) {
        this.projectList = projectList;
    }

    // 判断是否还有元素
    @Override
    public boolean hasNext() {
        return !(currentItem >= projectList.size() || projectList.get(currentItem) == null);
    }

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

}

然后看看Boss类有多少改动:

代码语言:javascript
复制
public class Boss {

    public static void main(String[] args) {

        IProject project = new Project();

        // 增加星球大战项目
        project.add("星球大战", 10, 100000);
        // 增加扭转时空项目
        project.add("扭转时空", 100, 1000000);
        // 增加超人改造项目
        project.add("超人改造", 10000, 10000000);
        // 增加100个其他项目
        for (int i = 4; i < 104; i++) {
            project.add("第" + i + "个项目", i * 5, i * 1000000);
        }

        IProjectIterator iterator = project.iterator();
        while(iterator.hasNext()) {
            IProject p = iterator.next();
            System.out.println(p.getProjectInfo());
        }

    }

}

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

现在迭代器模式有点没落了,从JDK1.2版本开始增加java.util.Iterator这个接口,并逐步把Iterator应用到各个集合类中,大部分集合类都有iterator()这个方法,我们可以通过这个方法去遍历集合类中的所有方法或属性,不需要自己再去写迭代器,所以基本上很少有项目再独立写迭代器了,直接使用List或者Map就可以完整的解决问题。

本文原书: 《您的设计模式》 作者:CBF4LIFE

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.10.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档