组合模式(Composite)

@@@模式定义:
将对象组合成树型结构以表示“部分-整体”的层次结构。
组合模式使得用户对单个对象和组合对象的使用具有一致性。

@@@练习示例: 
商品类别树

@@@示例代码:
<不用模式>
\product\Leaf.java

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

package product;



/**

 * 叶子对象

 */

public class Leaf {

    /**

     * 叶子对象的名字

     */

	private String name = "";

	

	/**

	 * 构造方法,传入叶子对象的名字

	 * @param name 叶子对象的名字

	 */

	public Leaf(String name) {

		this.name = name;

	}

	

	/**

	 * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字

	 * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进

	 */

	public void printStruct(String preStr) {

		System.out.println(preStr + "-" + name);

	}

}


\product\Composite.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

package product;



import java.util.ArrayList;

import java.util.Collection;



/**

 * 组合对象,可以包含其他组合对象或者叶子对象

 */

public class Composite {

    /**

     * 用来记录包含的其他组合对象

     */

	private Collection<Composite> childComposite =

		new ArrayList<Composite>();

	

	/**

	 * 用来记录包含的其他叶子对象

	 */

	private Collection<Leaf> childLeaf = 

		new ArrayList<Leaf>();

	

	/**

	 * 组合对象的名字

	 */

	private String name = "";

	

	/**

	 * 构造方法,传入组合对象的名字

	 * @param name 组合对象的名字

	 */

	public Composite(String name) {

		this.name = name;

	}

	

	/**

	 * 向组合对象加入被它包含的其他组合对象

	 * @param c 被它包含的其他组合对象

	 */

	public void addComposite(Composite c) {

		this.childComposite.add(c);

	}

	

	/**

	 * 向组合对象加入被它包含的叶子对象

	 * @param leaf 被它包含的叶子对象

	 */

	public void addLeaf(Leaf leaf) {

		this.childLeaf.add(leaf);

	}

	

	/**

	 * 输出组合对象自身的结构

	 * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进

	 */

	public void printStruct(String preStr) {

		// 先把自己输出去

		System.out.println(preStr + "" + this.name);

		// 然后添加一个空格,表示向后缩进一个空格,输出自己包含的叶子对象

		preStr += " ";

		for(Leaf leaf : childLeaf) {

			leaf.printStruct(preStr);

		}

		

		// 输出当前对象的字对象

		for(Composite c : childComposite) {

			// 递归输出每个子对象

			c.printStruct(preStr);

		}

	}

}


\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

package user;



import product.Composite;

import product.Leaf;



public class Client {

	public static void main(String[] args) {

        // 定义所有的组合对象

		Composite root = new Composite("服装");

		Composite c1 = new Composite("男装");

		Composite c2 = new Composite("女装");

		

		// 定义所有的叶子对象

		Leaf leaf1 = new Leaf("衬衣");

		Leaf leaf2 = new Leaf("夹克");

		Leaf leaf3 = new Leaf("裙子");

		Leaf leaf4 = new Leaf("套装");

		

		// 按照树的结构来组合组合对象和叶子对象

		root.addComposite(c1);

		root.addComposite(c2);

		c1.addLeaf(leaf1);

		c1.addLeaf(leaf2);

		c2.addLeaf(leaf3);

		c2.addLeaf(leaf4);

		

		// 调用根对象的输出功能来输出整棵树

		root.printStruct("");

	}

}


<问题描述>
必须区分组合对象和叶子对象,并进行有区别的对待;

<使用模式>
\pattern\Component.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

package pattern;



/**

 * 抽象的组件对象

 */

public abstract class Component {

    /**

     * 输出组件自身的名称

     */

	public abstract void printStruct(String preStr);

	

	/**

	 * 向组合对象中加入组件对象

	 * @param child 被加入组合对象中的组件对象

	 */

	public void addChild(Component child) {

		throw new UnsupportedOperationException("不支持该功能");

	}

	

	/**

	 * 从组合对象中移出某个组件对象

	 * @param child 被移出的组件对象

	 */

	public void removeChild(Component child) {

		throw new UnsupportedOperationException("不支持该功能");

	}

	

	/**

	 * 返回某个索引对应的组件对象

	 * @param index 需要获取的组件对象的索引,索引从0开始

	 * @return 索引对应的组件对象

	 */

	public Component getChildren(int index) {

		throw new UnsupportedOperationException("不支持该功能");		

	}

}


\pattern\Leaf.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

package pattern;



/**

 * 叶子对象

 */

public class Leaf extends Component {

	/**

     * 叶子对象的名字

     */

	private String name = "";

	

	/**

	 * 构造方法,传入叶子对象的名字

	 * @param name 叶子对象的名字

	 */

	public Leaf(String name) {

		this.name = name;

	}

	

	/**

	 * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字

	 * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进

	 */

	@Override

	public void printStruct(String preStr) {

		System.out.println(preStr + "-" + name);

	}

}


\pattern\Composite.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

package pattern;



import java.util.ArrayList;

import java.util.List;



/**

 * 组合对象,可以包含其他组合对象或者叶子对象

 */

public class Composite extends Component {

	/**

     * 用来存储组合对象中包含的子组件对象

     */

	private List<Component> childComonents = null;

	

	/**

	 * 组合对象的名字

	 */

	private String name = "";

	

	/**

	 * 构造方法,传入组合对象的名字

	 * @param name 组合对象的名字

	 */

	public Composite(String name) {

		this.name = name;

	}

	

	@Override

	public void addChild(Component child) {

		// 延迟初始化

		if (childComonents == null) {

			childComonents = new ArrayList<Component>();	

		}

		

		childComonents.add(child);

	}

	

	/**

	 * 输出组合对象自身的结构

	 * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进

	 */

	@Override

	public void printStruct(String preStr) {

		// 先把自己输出去

		System.out.println(preStr + "" + this.name);

		// 如果还包含有子组件,那么就输出这些子组件对象

		if (this.childComonents != null) {

			// 添加一个空格,表示向后缩进一个空格

			preStr += " ";

			// 输出当前对象的子对象

			for (Component c : childComonents) {

				// 递归输出每个子对象

				c.printStruct(preStr);

			}

		}

	}

}


\user\CilentPattern.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

package user;



import pattern.Component;

import pattern.Composite;

import pattern.Leaf;



public class CilentPattern {

	public static void main(String[] args) {

        // 定义所有的组合对象

		Component root = new Composite("服装");

		Component c1 = new Composite("男装");

		Component c2 = new Composite("女装");

		

		// 定义所有的叶子对象

		Component leaf1 = new Leaf("衬衣");

		Component leaf2 = new Leaf("夹克");

		Component leaf3 = new Leaf("裙子");

		Component leaf4 = new Leaf("套装");

		

		// 按照树的结构来组合组合对象和叶子对象

		root.addChild(c1);

		root.addChild(c2);

		c1.addChild(leaf1);

		c1.addChild(leaf2);

		c2.addChild(leaf3);

		c2.addChild(leaf4);

		

		// 调用根对象的输出功能来输出整棵树

		root.printStruct("");

	}

}


@@@模式的实现:
1. 有“安全性”和“透明性”两种实现方式;

@@@模式的优点:
1. 定义了包含基本对象和组合对象的类层次结构;
2. 统一了组合对象和叶子对象;
3. 简化了客户端调用;
4. 更容易扩展;

@@@模式的缺点:
1. 很难限制组合中的组件类型;

@@@模式的本质:
统一叶子对象和组合对象。

@@@模式体现的设计原则:
NA

 


 

你可能感兴趣的:(组合模式)