# 七大软件规划准则
# 规划形式-工厂形式
# 规划形式-单例形式
# 规划形式-原型形式
# 规划形式-策略形式
# 规划形式-职责链形式
# 规划形式-建造者形式
# 规划形式-深度分析署理形式
# 规划形式-门面形式
# 规划形式-装修器形式
# 规划形式-享元形式
# 规划形式-组合形式
# 规划形式-适配器形式
# 规划形式-桥接形式
# 规划形式-派遣形式
# 规划形式-模板办法形式
迭代器形式 (Iterator Pattern)又称为游标形式(Cursor Pattern),它供给一种顺序访问调集/ 容器目标元素的办法,而又无须暴露调集内部表示(到底是列表、栈仍是树等)。迭代器形式可认为不同的容器供给共同的 遍历行为,而不用关怀容器内容元素组成结构,归于行为型形式。
迭代器形式UML类图
完成代码如下(这儿运用的调集是list,也能够运用其他调集这儿就不逐个展现了)
public interface Iterator<T> {
T next();
boolean hasNext();
}
public class ConcreteIterator<T> implements Iterator<T>{
private final List<T> list;
private int cursor = 0;
public ConcreteIterator(List<T> list){
this.list = list;
}
@Override
public T next() {
if(hasNext()) {
return list.get(cursor++);
}
return null;
}
@Override
public boolean hasNext() {
return list.size() > cursor;
}
}
public interface IAggregate {
void add(User user);
void remove(User user);
Iterator<User> iterator();
}
public class ConcreteAggregate implements IAggregate{
private final List<User> users = new ArrayList<>();
@Override
public void add(User user) {
users.add(user);
}
@Override
public void remove(User user) {
users.remove(user);
}
@Override
public Iterator<User> iterator() {
return new ConcreteIterator<>(users);
}
}
public class Test {
public static void main(String[] args) {
User user1 = new User("张三", "123");
User user2 = new User("张三2", "123");
User user3 = new User("张三3", "123");
User user4 = new User("张三4", "123");
User user5 = new User("张三5", "123");
User user6 = new User("张三6", "123");
User user7 = new User("张三7", "123");
ConcreteAggregate concreteAggregate = new ConcreteAggregate();
concreteAggregate.add(user1);
concreteAggregate.add(user2);
concreteAggregate.add(user3);
concreteAggregate.add(user4);
concreteAggregate.add(user5);
concreteAggregate.add(user6);
concreteAggregate.add(user7);
Iterator<User> iterator = concreteAggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toString());
}
}
}
看完这些代码后或许有些人会说直接for循环不是很简单,确实许多时分for循环确实很简单,可是遇到上文中的删除操作那你的for循环是不是会有点问题,当然还有人说这个问题很好处理。当你遇到的调集是树、图再用for循环是不是很杂乱,而且你的事务中有许多这样的结构的时分你的for循环是不是到处都是,如果咱们写一个迭代器,杂乱遍历逻辑放到迭代器里边运用到的地方只需要调用岂不是很方便,代码也相对更优雅一些
迭代器在源码中的运用
咱们知道java中的调集终究都会完成Iterable
接口如下图所示:
咱们能够看一下Iterable
源码
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
发现这儿就会回了迭代器再看 Iterator
源码
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
发现和上文中界说的简直一样
这儿咱们能够看一下迭代器的详细完成(这儿拿List举例)
发现详细完成类是 ListItr
再看源码:
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException(e);
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
这儿面就完成了List的遍历
迭代器形式的优缺陷
优点:
- 多态迭代:为不同的聚合结构供给共同的遍历接口,即一个迭代接口能够访问不同的调集目标
- 简化调集目标接口:迭代器形式将调集目标自身应该供给的元索迭代接口抽取到了迭代器 中,使调集目标无须关怀详细迭代行为
- 元素迭代功用多样化:每个调集目标都能够供给一个或多个不同的迭代器,使的同种元素聚 合结构能够有不同的迭代行为;
- 解耦迭代与调集:迭代器形式封装了详细的迭代算法,迭代算法的改变,不会影响到调集 目标的架构
缺陷:
关于比较简单的遍历(像数组或者有序列表),运用迭代器方式遍历较为繁琐。
正常情况下咱们在写项目的时分很少会用到迭代器形式,常用调集底层都帮咱们完成了迭代器,所以咱们用就能够了。一般情况下咱们都是在运用轮子而非造轮子