设计模式——组合模式

COMPOSITE组合

1、 意图

将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

2、 适用性

在下面情况下可以使用Composite模式

  •  想表示对象的整体-部分层次结构
  • 希望用户忽略组合对象与单个对象的不同,用户将同一使用组合结构中的所有对象。

3、 结构

4、 参与者

        Component

                  ——为组合中的对象声明接口。

                  ——在适当的情况下,实现所有类共有接口的缺省方法。

                  ——声明一个接口用于访问和管理Component的子组件。

                  ——(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。

         Leaf

                   ——在组合中表示叶节点对象,叶节点没有子节点。

                   ——在组合中定义图元对象的行为。

         Composite

                   ——定义有子部件的那些部件的行为。

                   ——存储子部件。

                   ——在Component接口中实现与子部件有关的操作。

         Client

                   ——通过Component接口操作组合部件的对象。

5、 协作

用户使用Component类接口与组合结构中的对象进行交互。如果接收者是一个叶节点,则直接处理请求。如果接收者是Composite,它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。

6、 效果

1)   定义了包含基本对象和组合对象的类层次结构;基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断递归下去。在客户代码中,任何用到基本对象的地方都可以使用组合对象。

2)  简化客户代码;客户可以一致地使用组合结构和单个对象。通常用户不知道(也不关心)处理的是一个叶节点还是一个组合组件。这就简化了客户代码,因为在定义组合的那些类中不需要写一些充斥着选择语句的函数。

3)  使得更容易增加新类型的组件;新定义的Composite或Leaf子类自动地与已有的结构和客户代码一起工作,客户程序不需要因新的Component类而改变。

4)  使你的设计更一般化;容易增加新组件也会产生一些问题,那就是很难限制组合中的组件。有时你希望一个组合只能有某些特定的组件。使用Composite时,你不能依赖类型系统施加这些约束,而必须在运行时刻进行检查。

7、 实现

下面是使用Component模式时所以考虑的实现问题:

1)  显式的父组件引用;保持从子部件到父部件的引用能简化组合结构的遍历和管理。

2)  共享组件;共享组件是很有用的,如它可以减少对存贮的需求。但是当一个组件只有一个父组件时,很难共享组件。一个可行的解决方法是为子部件存贮多个父部件,但当一个请求在结构中向上传递时,这种方法会导致多义性。

3)  最大化Component接口;Composite模式的目的之一是使得客户不知道他们正在使用的具体的Leaf和Composite类。为了达到这一目的,Composite类应为Leaf和Composite类尽可能多定义一些公共操作。

4)  声明管理子部件的操作;即在安全性和透明性之间的选择

5)  子部件排序;可以用Iterator模式进行。

6)  使用高速缓冲存贮改善性能;如果需要对组合进行频繁的遍历或查找,Composite类可以缓冲存储对它的子节点进行遍历或查找的相关信息。

8、 代码示例

Component

package com.examples.pattern.component;


/**
 *	抽象的组件对象,为组合中的对象声明接口,实现接口的缺省行为
 */
public abstract class Component {
	
	
	/**
	 * 子组件对象的一些操作
	 */
	public abstract void someOperation();
	
	/**
	 * 向组合对象中加入组件对象
	 * @param child	被加入组合对象中的组合对象
	 */
	public void addChild(Component child){
		throw new UnsupportedOperationException("对象不支持这个功能");
	}
	
	/**
	 * 向组合对象中移除某个组件对象
	 * @param child	被移除组合的对象
	 */
	public void remove(Component child){
		throw new UnsupportedOperationException("对象不支持这个功能");
	}
	
	/**
	 * 返回某个索引对应的组件对象
	 * @param index	需要获取的组件对象的索引,索引从0开始
	 * @return	索引对象的组件对象
	 */
	public Component getChildren(int index){
		throw new UnsupportedOperationException("对象不支持这个功能");
	}

}
Composite
package com.examples.pattern.component;

import java.util.ArrayList;
import java.util.List;

/**
 *	组合对象,通常需要存储子对象,定义有子部件的部件行为
 *	并实现在Component里面定义的与子部件有关的操作
 */
public class Composite extends Component {
	
	/**
	 * 用来存储组合对象中包含的子组件对象
	 */
	private List<Composite> childComponents = null;

	@Override
	public void someOperation() {
		if(childComponents != null){
			for(Component c : childComponents){
				c.someOperation();	//递归地进行子组件相应方法的调用
			}
		}

	}

	@Override
	public void addChild(Component child) {
		if(childComponents == null){
			childComponents = new ArrayList<Composite>();
		}
		childComponents.add(this);
	}

	@Override
	public void remove(Component child) {
		if(childComponents != null){
			childComponents.remove(child);
		}
	}

	@Override
	public Component getChildren(int index) {
		
		if(childComponents != null){
			if(index >= 0 && index < childComponents.size()){
				return childComponents.get(index);
			}
		}
		
		return null;
	}
	
	

}
Leaf
package com.examples.pattern.component;

/**
 *	叶子对象,叶子对象不再包含其他子对象
 */
public class Leaf extends Component{

	@Override
	public void someOperation() {
		
	}

}
Client
package com.examples.pattern.component;

public class Client {
	
	public static void main(String[] args) {
		
		//定义多个Composite对象
		Component root = new Composite();
		Component c1 = new Composite();
		Component c2 = new Composite();
		
		//定义多个叶子对象
		Component leaf1 = new Leaf();
		Component leaf2 = new Leaf();
		Component leaf3 = new Leaf();
		
		//组合成树形的对象结构
		root.addChild(c1);
		root.addChild(c2);
		root.addChild(leaf1);
		c1.addChild(leaf2);
		c2.addChild(leaf3);
		
		Component o = root.getChildren(1);
		System.out.println(o);
	}

}



 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值