【读码练习/cron4j】(二)半个设计模式:不暴露底层表现(简化了的迭代器模式)
重读笔记第一次:
这篇总结写的不好,自己的东西重看的也比较累,不高兴改了,就写这里吧。
主要总结迭代器的两个功能的左边那个:不暴露底层,也可以说是统一接口以备泛用。
其实cron4j也不是没有返回迭代器,只是不如教科书上的那样死板而已。
再补充下java类库的aggregate角色和iterator角色。
分别是java.lang.iterable和java.util.iterator
就这样吧
经典的迭代器模式,有两个功能
1、提供一个方式顺序访问集合
2、不暴露底层的表现形式。
经典的迭代模式有四个角色。
aggregate、concreteAggregate、iterator、concreteIterator。
aggreate里通常有一个方法 iterator createrIterator(); 返回迭代器
iterator里也通常有一个方法 next() 从集合顺序访问元素
cron4j的简化
在cron4j这个模式得到简化。(TaskCollector是aggregate角色,FileTableCollector是concreteAggregate)
1、没有了抽象的iterator角色。
2、interator也没有了next()。
publicinterface TaskCollector {
public TaskTable getTasks();
}
1 class FileTaskCollector implements TaskCollector {
2
3 private ArrayList files =new ArrayList();
4
5 publicsynchronizedvoid addFile(File file) {
6 files.add(file);
7 }
8
9 publicsynchronizedvoid removeFile(File file) {
10 files.remove(file);
11 }
12
13 publicsynchronized File[] getFiles() {
14 int size = files.size();
15 File[] ret =new File[size];
16 for (int i =0; i < size; i++) {
17 ret[i] = (File) files.get(i);
18 }
19 return ret;
20 }
21
22 publicsynchronized TaskTable getTasks() {
23 TaskTable ret =new TaskTable();
24 int size = files.size();
25 for (int i =0; i < size; i++) {
26 File f = (File) files.get(i);
27 TaskTable aux =null;
28 try {
29 aux = CronParser.parse(f);
30 } catch (IOException e) {
31 Exception e1 =new Exception("Cannot parse cron file: "
32 + f.getAbsolutePath(), e);
33 e1.printStackTrace();
34 }
35 if (aux !=null) {
36 int auxSize = aux.size();
37 for (int j =0; j < auxSize; j++) {
38 ret.add(aux.getSchedulingPattern(j), aux.getTask(j));
39 }
40 }
41 }
42 return ret;
43 }
44
45 }
1 publicclass TaskTable {
2
3 privateint size =0;
4
5 private ArrayList patterns =new ArrayList();
6
7 private ArrayList tasks =new ArrayList();
8
9 publicvoid add(SchedulingPattern pattern, Task task) {
10 patterns.add(pattern);
11 tasks.add(task);
12 size++;
13 }
14
15 publicint size() {
16 return size;
17 }
18
19 public Task getTask(int index) throws IndexOutOfBoundsException {
20 return (Task) tasks.get(index);
21 }
22
23
24 public SchedulingPattern getSchedulingPattern(int index)
25 throws IndexOutOfBoundsException {
26 return (SchedulingPattern) patterns.get(index);
27 }
28
29 publicvoid remove(int index) throws IndexOutOfBoundsException {
30 tasks.remove(index);
31 patterns.remove(index);
32 size--;
33 }
34
35 }
这样的简化好还是不好呢?
从代码看,迭代器的迭代方法next()被省略掉了。如果要遍历的话,必须通过size()、getTask(index),getSchedulingPattern(index)
但如果我们去实现一个next方法,可能还要把一对Task、和Pattern包装成一个类,然后还要再包装他们的方法。
这样似乎就得不偿失了。
思考
迭代器的重点之一是把集合(File对象或者其他Object)和表现形式(TaskTable)分离。可以单独用于场景
迭代器模式,如果要迭代的对象复杂,不易封装,next()方法不要也罢。
模式对应场景可以提高对应的效率,不必拘泥形式。