设计模式笔记(八)--迭代器模式、组合模式

迭代器模式(Iterator Pattern)

提供一个方法顺序访问一个聚合对象中的元素,而不暴露其内部的表示。

简单点说,Java集合框架中的集合:ArrayList、LinkedList、Vector、Stack、HashMap、HashTable等容器,还有对象数组,要想遍历出里面的所有对象基本每个容器有每个容器的遍历方式,现在我们想不管用什么容器存储这些对象,我都用相同的方式进行遍历。因此,我们需要封装“遍历集合内每个对象的过程”,这个迭代器接口需要有hasNext()方法判断集合内还有没有元素待遍历,有next()方法获取集合内当前遍历到的元素,有remove()方法删除遍历项。而具体的迭代器需要维护该集合以及实现该集合自己的遍历方式。


注意:这里所说的容器、集合、聚合都是一个概念,都是指对象的集合,像ArrayList等。

迭代器模式把元素遍历的责任交给迭代器,而不是聚合对象。让聚合对象的职责更明确更单一,符合单一职责原则。

客户只关心聚合类和迭代器接口,用这个迭代器接口就可以遍历这个聚合(Aggregate)了,不用关心到底用什么具体迭代器实现(每一个具体聚合都要负责实例化一个具体迭代器(所有的具体迭代器都要实现迭代器接口),并返回给客户以便客户遍历自己)。这样,就将客户代码从集合对象的实现解耦了。

  • 单一责任原则
    • 一个类应该只有一个引起变化的原因
    • 类的每个责任都有改变的潜在区域。超过一个责任,意味着超过一个改变的区域。
  • Java5以后遍历集合的时候,不需要显示创建迭代器,用for/in语句就行了for (Object obj : collection) { }

组合模式(Composite Pattern)

允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。

简单点说,就是递归包含,比如说一个菜单,包含多个菜单项,而有的菜单项也可以是一个菜单,这个菜单又包含多个菜单项或子菜单,这种情况下就需要一个接口来一致处理组合(菜单)和个别对象(菜单项)了。


组件有两种:组合和叶节点元素。组合包含组件。组合持有一群孩子,这些孩子可以是组合也可以是叶节点元素。上面的例子中,菜单可以包含其它菜单也可以包含菜单项。

为了能用统一的做法来处理菜单和菜单项,需要创建一个菜单组件接口来作为菜单和菜单项共同的接口。

菜单和菜单项都是组件,而add(Component)、remove(Component)、getChild(int)用来操纵这些组件。

对于菜单的遍历,要用组合迭代器(Composite Iterator),而菜单项的遍历用空迭代器(Null Iterator)。

组合迭代器:

import java.util.Iterator;
import java.util.Stack;

public class CompositeIterator implements Iterator {

	Stack stack = new Stack();//存放迭代器的栈

	public CompositeIterator(Iterator iterator) {
		stack.push(iterator);//将顶层组合的迭代器压栈
	}

	public boolean hasNext() {
		// TODO Auto-generated method stub
		if (stack.empty()) {
			return false;
		} else {
			Iterator iterator = (Iterator) stack.peek();//查看(peek)栈顶的迭代器
			if (!iterator.hasNext()) {//如果没有元素了,弹出栈,递归调用hasNext()看下层还有没有元素
				stack.pop();
				return hasNext();
			} else {
				return true;
			}
		}
	}

	public Object next() {
		// TODO Auto-generated method stub
		if (hasNext()) {
			Iterator iterator = (Iterator) stack.peek();
			MenuComponent component = (MenuComponent) iterator.next();
			if (component instanceof Menu) {//如果元素是个菜单,将它的迭代器压栈
				statck.push(component.createIterator());
			}
			return component;
		} else {
			return null;
		}
	}

	public void remove() {
		throw new UnsupportedOperationException();
	}
}

空迭代器:

import java.util.Iterator;

public class NullIterator implements Iterator {

	// 什么事情都不做,所以永远返回false
	public boolean hasNext() {
		// TODO Auto-generated method stub
		return false;
	}

	public Object next() {
		// TODO Auto-generated method stub
		return null;
	}

	public void remove() {
		throw new UnsupportedOperationException();
	}
}


这就像Android里面View和ViewGroup的关系,ViewGroup是一个View子类,而ViewGroup可以包含多个ViewGroup或者View,而对于绘制系统来说我都当作View看待,不管你是ViewGroup还是什么View我都可以遍历、测量、布局、绘制。



发布了48 篇原创文章 · 获赞 168 · 访问量 56万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览