zoukankan      html  css  js  c++  java
  • 迭代器与组合模式

    迭代器(Iterator)与组合模式(Composite)

       迭代器是我们经常接触的东西,当然,我们更习惯使用的是类似这样的代码:

            String[] arr = new String[]{"one", "two", "three"};
            for (String num : arr) {
                System.out.println(num);
            }

      

      而完整的迭代器是这样子的:

     

            List<String> numberList = new ArrayList<String>();
            numberList.add("one");
            numberList.add("two");
            numberList.add("three");
            Iterator<String> iterator = numberList.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }

      我们打开List接口的实现类ArrayList,可以发现里面有个私有类,其实就是实现了迭代器接口的一个类。

      那么我们为什么要使用迭代器,或者在什么场景下去使用它?迭代器意图在于提供一个统一的遍历回调入口,有点像是这样子:

    package top.gabin.design.iterator;
    
    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    /**
     * Class description
     * @author linjiabin on  16/5/15
     */
    public class IteratorDemo {
    
        @Test
        public void testDemo() {
            List<String> numberList = new ArrayList<String>();
            numberList.add("one");
            numberList.add("two");
            numberList.add("three");
            printListForUpdateCase(numberList, new DealString() {
                public String updateCase(String content) {
                    if (content == null) {
                        return null;
                    }
                    return content.toUpperCase();
                }
            });
        }
    
        private void printListForUpdateCase(List<String> list, DealString dealString) {
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                String next = iterator.next();
                System.out.println(dealString.updateCase(next));
            }
        }
    
        private interface DealString {
            String updateCase(String content);
        }
    
    }

      提供一个统一的遍历入口的意义在于,你不再需要知道这个数组或者集合容器的结构,换言之,如果没有迭代器的存在,你将需要使用类似这样的代码:

            List<String> numberList = new ArrayList<String>();
            numberList.add("one");
            numberList.add("two");
            numberList.add("three");
    
            for (int i = 0; i < numberList.size(); i++) {
                System.out.println(numberList.get(i));
            }

      首先你需要知道这个集合的长度获取方法size(),其次你需要知道根据索引获取元素的方法get(index)。相比而言,Iterator是不是简单了许多?

      组合模式:允许你将对象组织成树形结构,表现为"整体/部分"的层级结构,允许用户使用一致的方式调用个别对象和组合对象。

      我们抓住关键的词:树形结构,好吧,这是一个经常需要用到递归的结构。树形结构一般分为根(root)、树节点、叶节点,根有点像是Linux系统中的根目录,树节点则是文件夹,那么对了,叶节点则是文件。假设我们现在需要遍历所有文件名称(包含文件夹的名称)。

      

    package top.gabin.design.composite;
    
    import java.io.File;
    
    /**
     *
     * @author linjiabin on  16/5/15
     */
    public class AccessDirectory {
    
        /**
         * 遍历打印文件
         * @param file
         */
        public void printListFile(File file) {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                for (File f : files) {
                    printListFile(f);
                }
            } else {
                System.out.println(file.getName());
            }
        }
    
    }

    测试类代码:

    package top.gabin.design.composite;
    
    import org.junit.Test;
    
    import java.io.File;
    
    /**
     * Class description
     *
     * @author linjiabin on  16/5/15
     */
    public class TestAccessDirectory {
        @Test
        public void testPrintDirectory() {
            File file = new File("/data/mall/mysql");
            new AccessDirectory().printListFile(file);
        }
    }

    打印出来的结果是:

    .DS_Store
    .DS_Store
    mysql.000001
    mysql.000002
    mysql.000003
    mysql.000004
    mysql.000005
    mysql.000006
    mysql.000007
    mysql.000008
    mysql.000009
    mysql.000010
    mysql.000011
    mysql.000012
    mysql.000013
    mysql.000014
    mysql.000015
    mysql.000016
    mysql.000017
    mysql.000018
    mysql.000019
    mysql.000020
    mysql.index
    roma.log
    slow.log

    当然这不是关键,而是正如你所看到的一样,文件夹的类型也是File,文件的类型也是File,然后你不可能在文件的对象后面调用listFile方法,不是吗?这就是组合模式的妙处,你可以将这两者在递归访问的过程中,调用几乎相同的代码(如果你不想知道它是文件还是文件夹的情况下)。

  • 相关阅读:
    阿里云OSS进行文件下载时,报NOSuchKeys: com.aliyun.oss.OSSException: The specified key does not exist.
    [JAVA异常]ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2 JDWP exit erro
    mybatis 中的<![CDATA[ ]]>
    HttpClients.custom的创建
    RestTemplate可以自定义重试次数
    RegxUtils正则表达式工具类
    MYSQL中 != 和 is not的区别
    ccna ccnp ccie 区别
    【IDEA】IDEA SpringBoot访问不到webapp下的内容
    日志 | logback | logback-spring.xml
  • 原文地址:https://www.cnblogs.com/gabin/p/5494719.html
Copyright © 2011-2022 走看看