标签:
迭代器(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方法,不是吗?这就是组合模式的妙处,你可以将这两者在递归访问的过程中,调用几乎相同的代码(如果你不想知道它是文件还是文件夹的情况下)。
标签:
原文地址:http://www.cnblogs.com/gabin/p/5494719.html