◎筱米加步枪◎.Blog

Happy coding

组合模式

总结关于组合模式的目的:

客户程序可以向处理简单元素一样来处理复杂元素。

关于组合模式的作用:

可用于处理对象的部分-整体结构,经常用于处理拥有树状结构的问题。

对应的类图:

下列贴一段代码来说明应用组合模式+迭代器来模拟对树的遍历,顺便复习了数据结构中的树相关知识。本代码参考网上相关代码:

/**
 * 结点接口
 * @author ChenST
 */
public interface Node {
	
	/**
	 * 添加结点
	 * @param node
	 */
	public void add(Node node);
	
	/**
	 * 获取一个迭代器
	 * @return
	 */
	public Iterator<Node> iterator();
}
/**
 * 抽象结点,主要实现toString方法,可用于识别各个结点
 * @author ChenST
 *
 */
public abstract class AbstractNode implements Node{
	
	/** 结点名字 */
	protected String nodeName;
	
	public AbstractNode(String nodeName){
		this.nodeName = nodeName;
	}

	public String toString(){
		return nodeName;
	}
}
/**
 * 叶子结点,不允许有子结点
 * @author ChenST
 */
public class LeafNode extends AbstractNode {

	public LeafNode(String nodeName) {
		super(nodeName);
	}

	@Override
	public void add(Node node) {
		throw new UnsupportedOperationException("叶子结点不能添加结点");
	}

	@Override
	public Iterator<Node> iterator() {
		//返回空的迭代器,永远无法进行迭代
		return new NullIterator<Node>();
	}
}
/**
 * 枝结点,可存储多数叶子结点
 * @author ChenST
 */
public class BranchNode extends AbstractNode {

	//树枝结点下的所有孩子结点
	private List<Node> childs = new ArrayList<Node>();
	
	public BranchNode(String nodeName) {
		super(nodeName);
	}

	@Override
	public void add(Node node) {
		childs.add(node);
	}

	@Override
	public Iterator<Node> iterator() {
		return childs.iterator();
	}
}
/**
 * 空的迭代器
 * @author ChenST
 *
 * @param <T>
 */
public class NullIterator<T> implements Iterator<T> {

	@Override
	public boolean hasNext() {
		//永远没有下一个结点
		return false;
	}

	@Override
	public T next() {
		//永远为空
		return null;
	}

	@Override
	public void remove() {
		//没有移除方法
	}
}
/**
 * 深度优先迭代器
 * @author ChenST
 */
public class DepthFirstIterrator implements Iterator<Node> {

	//堆栈
	private Stack<Iterator<Node>> stack = new Stack<Iterator<Node>>();
	
	public DepthFirstIterrator(Iterator<Node> iter){
		this.stack.push(iter);
	}
	
	@Override
	public boolean hasNext() {
		if(stack.isEmpty()){
			return false;
		}else{
			Iterator<Node> iter = this.stack.peek();
			if(iter.hasNext()){
				return true;
			}else{
				this.stack.pop();
				return hasNext();
			}
		}
	}

	@Override
	public Node next() {
		if(hasNext()){
			Iterator<Node> iter = this.stack.peek();
			Node node = iter.next();
			if(node instanceof BranchNode){
				this.stack.push(node.iterator());
			}
			return node;
		}
		return null;
	}

	@Override
	public void remove() {
		throw new UnsupportedOperationException("不支持移除操作");
	}
}
/**
 * 广度优先算法的迭代器
 * @author ChenST
 */
public class BreadthFirstIterator implements Iterator<Node> {

	//存储临时结点操作的队列
	private Queue<Iterator<Node>> queue = new LinkedList<Iterator<Node>>();
	
	public BreadthFirstIterator(Iterator<Node> iter){
		queue.offer(iter);
	}
	
	@Override
	public boolean hasNext() {
		if(queue.isEmpty()){
			return false;
		}else{
			Iterator<Node> iter = queue.peek();
			if(iter.hasNext()){
				return true;
			}else{
				queue.poll();
				return hasNext();
			}
		}
	}

	@Override
	public Node next() {
		if (hasNext()) {
			Iterator<Node> it = queue.peek();
			Node node = it.next();
			if(node instanceof BranchNode){
				queue.offer(node.iterator());
			}
			return node;
		}
		return null;
	}

	@Override
	public void remove() {
		throw new UnsupportedOperationException("不支持移除操作");
	}
}
public class Test {

	public static void main(String[] args) {
		//构建树
		Node A = new BranchNode("A");
		Node B = new BranchNode("B");
		Node C = new BranchNode("C");
		Node D = new BranchNode("D");
		Node E = new LeafNode("E");
		Node F = new LeafNode("F");
		Node G = new LeafNode("G");
		Node K = new LeafNode("K");
		A.add(B);
		A.add(C);
		B.add(D);
		B.add(E);
		C.add(F);
		D.add(G);
		D.add(K);

		//深度优先迭代器
		System.out.print("深度优先迭代器:"+A);
		Iterator<Node> iterDepth = new DepthFirstIterrator(A.iterator());
		while(iterDepth.hasNext()){
			System.out.print(iterDepth.next());
		}
		
		//广度优先迭代器
		Iterator<Node> iterBreadth = new BreadthFirstIterator(A.iterator());
		System.out.print("\n广度优先迭代器:"+A);
		while(iterBreadth.hasNext()){
			System.out.print(iterBreadth.next());
		}
	}
}
深度优先迭代器:ABDGKECF
广度优先迭代器:ABCDEFGK

本例子利用自定义迭代器(深度优先迭代器和广度优先迭代器)对构建的树进行了访问。可以看到利用组合模式不管对叶子结点访问还是对整颗树进行访问或者对树的某个子树进行访问都是用同样的方法都可以达到目的。这就是组合模式的核心