前言:
来源于《head first 设计模式》。当作读书笔记了,这次看的是第9章模版方法模式。最后剩下没几章了,这几天花时间看完了,现在来才来写下记录。
迭代器模式的概念
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示
适配器模式的uml图
角色介绍:
- Clinet:代表客户代码
- Aggregate:一个共同的接口供所有的聚合使用,将客户代码与具体的集合对象实现解耦。
- ConcreteAggregate:一个具体的聚合持用一个对象的集合,并实现一个方法,利用此方法返回该集合的迭代器。
- Iterator:这是所有迭代器都必须实现的接口,它包含一些迭代器所需方法,用于操作集合
- ConcreteIterator:这个具体的迭代器负责管理目前遍历的位置。
例子
光说无用,这里用java源码来解释。
Collection,所有集合的顶部接口-----ConcreteAggregate
public interface Collection<E> extends Iterable<E> {
Iterator<E> iterator();
}
这里只截取部分与迭代器相关的代码。这里的iterator()相当于createiterator()都是获取一个迭代器。
Iterator------Iterator
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
这是所有迭代器的都必须实现的接口,包含了一些基本的操作集合的方法
HashIterator是hashMap中的内部类-------ConcreteIterator
abstract class HashIterator {
Node<K,V> next; // next entry to return
Node<K,V> current; // current entry
int expectedModCount; // for fast-fail
int index; // current slot
HashIterator() {
expectedModCount = modCount;
Node<K,V>[] t = table;
current = next = null;
index = 0;
if (t != null && size > 0) { // advance to first entry
do {} while (index < t.length && (next = t[index++]) == null);
}
}
public final boolean hasNext() {
return next != null;
}
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
public final void remove() {
Node<K,V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
K key = p.key;
removeNode(hash(key), key, null, false, false);
expectedModCount = modCount;
}
}
final class KeyIterator extends HashIterator
implements Iterator<K> {
public final K next() { return nextNode().key; }
}
final class ValueIterator extends HashIterator
implements Iterator<V> {
public final V next() { return nextNode().value; }
}
final class EntryIterator extends HashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
HashIterator实现了所有的iterator的基本方法,而其只是抽象类,正在实现Iterator的是继承了HashIterator的EntryIterator、ValueIterator、KeyIterator。其实这里只是把重复代码抽象出来到HashIterator,基本实现是于uml无区别的。都是实现迭代器接口的方法。
EntrySet-----ConcreteAggregate
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public final Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
}
唏嘘,选错了集合选了个hashmap,hashMap的迭代器是针对key的或者针对entry的,所以有点乱哈哈哈哈哈,这里就是他内部的EntrySet追根到底他还是实现了collection,实现了方法返回key value的迭代器。我们一般调用就是获取的话是用,map.entrySet.Iterator获取key value的迭代器。差不多哈。
总结:
其实就是每个集合都不会有它不一样的遍历方法,我们采用迭代器的模式来对遍历过程进行封装,而我们不需要知道内部是如何访问的,即不再知道我们是用什么集合来存储数据的,只需得到其迭代器即可操作集合。
组合模式
组合模式的概念
组合模式允许将对象组合成属性结构来表现“整体/部分”层次结构,组合能让客户以一致的方式处理个别对象以及对象组合。
组合模式uml图
这是网上找到一张图,偷了点懒。
特点:
树形结构表示对象组合
忽略对象组合和对象个体之间的差别,即相同的操作既可以作用于对象组合,也可以作用与对象个体
注意:
因为继承方法中,有些方法只有对叶子节点有意义,而有些方法只对非叶子节点有意义,我们可以将基类的方法默认实现为抛出UnsupportedOperationException,如果方法无意义,则无需修改默认继承就可以了
总结:
其实就是相当于树,每个节点可能是单个物体、也可能是一个集合。借此来进行分类,构建一个巨大的分类菜单