欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式——组合模式(Composite)

程序员文章站 2022-05-04 17:54:54
...

Composite模式定义:

    将对象以树形结构组织起来,以达成部分-整体的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。

    Composite比较容易理解,想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时,Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。

Composite好处:

    1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。

    2.更容易在组合体内加入对象部件,客户端不必因为加入了新的对象部件而更改代码。

如何使用Composite?

    首先定义一个接口或抽象类,这是设计模式通用方式了,其他设计模式对接口内部定义限制不多,Composite却有个规定,那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们(或称部件Component)。

    Composite模式要对组合的对象进行管理,所以在一定位置给予对象的相关管理方法,如:add(),remove().Composite模式中对象的管理有两种方案。

    1.安全方式:此方式只允许树枝构件有对象的管理方法。

    2.透明方式:此方式只允许树枝和树叶都有对象的管理方法,但树叶对象中的管理方法无实际意义。

一.UML示意图


    设计模式——组合模式(Composite)
            
    
    博客分类: 设计模式 组合模式composite模式java设计模式 
 二.组成部分

    抽象构件:抽象组合对象的公共行为接口

    树叶构件:树叶对象,没有下级子对象

    树枝构件:树枝对象,树枝对象可以包含一个或多个其他树枝或树叶对象

三.代码例子

1.抽象构件

 

package com.composite;

public interface IFile {
	/**
	 * 返回自己的实例
	 * @return
	 */
	public IFile getComposite();
	
	/**
	 * 获取名字
	 * @return
	 */
	public String getName();
	
	/**
	 * 设置名字
	 * @param name
	 */
	public void setName(String name);
	
	/**
	 * 获取深度
	 * @return
	 */
	public int getDeep();
	/**
	 * 设置深度
	 * @param deep
	 */
	public void setDeep(int deep);
}

 2.叶子构件

 

package com.composite;


public class File implements IFile{

	/**
	 * 文件名字
	 */
	private String name;
	/**
	 * 层级深度,根为0
	 */
	private int deep;
	
	public File(String name) {
		this.name = name;
	}
	
	@Override
	public IFile getComposite() {
		return this;
	}
	
	@Override
	public String getName() {
		return name;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int getDeep() {
		return deep;
	}

	@Override
	public void setDeep(int deep) {
		this.deep = deep;
	}

}

  3.树枝构件

 

package com.composite;

import java.util.Vector;

public class Folder implements IFile{

	/**
	 * 文件名字
	 */
	private String name;
	/**
	 * 层级深度,根为0
	 */
	private int deep;
	
	/**
	 * 直接子文件(夹)集合
	 */
	private Vector<IFile> component = new Vector<IFile>();
	
	public Folder(String name) {
		this.name = name;
	}
	
	@Override
	public IFile getComposite() {
		return this;
	}
	
	/**
	 * 新增一个文件或文件夹
	 * @param file
	 */
	public void add(IFile file)
	{
		component.addElement(file);
		file.setDeep(this.deep+1);
	}
	
	/**
	 * 删除一个文件或文件夹
	 * @param file
	 */
	public void remove(IFile file)
	{
		component.removeElement(file);
	}
	
	/**
	 * 获取直接子文件(夹)集合
	 * @return
	 */
	public Vector<IFile> getComponent()
	{
		return this.component;
	}
	
	@Override
	public String getName() {
		return name;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int getDeep() {
		return deep;
	}

	@Override
	public void setDeep(int deep) {
		this.deep = deep;
	}

}

 4.测试

 

package com.composite;

import java.util.Iterator;
import java.util.Vector;

public class Test {
	public static void main(String[] args) {
		Folder root = new Folder("根节点");
		
		Folder folder1_1 = new Folder("1_分支1");
		
		Folder folder1_2 = new Folder("1_分支2");
		
		File f1_1 = new File("1_叶1");
		
		File f1_2 = new File("1_叶2");
		
		File f1_3 = new File("1_叶3");
		
		Folder folder2_1 = new Folder("2_分支1");
		
		Folder folder2_2 = new Folder("2_分支2");
		
		File f2_1 = new File("2_叶1");
		
		File f2_2 = new File("2_叶2");
		
		root.add(folder1_1);
		root.add(folder1_2);
		root.add(f1_1);
		root.add(f1_2);
		root.add(f1_3);
		
		folder1_2.add(folder2_1);
		folder1_2.add(folder2_2);
		folder1_2.add(f2_1);
		
		folder2_2.add(f2_2);
		
		outTree(root);
	}
	
	public static void outTree(Folder folder)
	{
		System.out.println(folder.getName());
		iterateTree(folder);
	}
	
	public static void iterateTree(Folder folder)
	{
		Vector<IFile> clist = folder.getComponent();
		for(Iterator<IFile> it = clist.iterator();it.hasNext();)
		{
			IFile em = it.next();
			if(em instanceof Folder)
			{
				Folder cm = (Folder) em;
				System.out.println(getIndents(em.getDeep())+cm.getName());
				iterateTree(cm);
			}else
			{
				System.out.println(getIndents(em.getDeep())+((File)em).getName());
			}
		}
	}
	
	public static String getIndents(int x)
	{
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<x;i++)
		{
			sb.append("\t");
		}
		return sb.toString();
	}
}

 5.结果


    设计模式——组合模式(Composite)
            
    
    博客分类: 设计模式 组合模式composite模式java设计模式 

四.总结

    组合模式是对象的结构模式。在以后的项目中,如果遇到对象组合的情况,即也符合树结构的。可以考虑下此模式。此模式中讲述了安全方式和透明方式。
    安全方式:抽象构件上只提供树叶和树枝公共的方法,没提供树枝独有的管理等方法(add(),remove())。这样的好处是安全,用户不会在树叶上使用add()等管理方法,缺点是不够透明,用户必须知识当前对象为树叶还是树枝(向下转型)。

    透明方式:抽象构件上提供了满足树枝的所有方法(包括add(),remove()),这样做的好处是,用户可以任意执行对象的add()remove()管理对象。缺点是如果用户在树叶上执行管理方式(add(),remove())时,在编译期不会有错,但在执行期会报错,这样不容易被发觉错误出在哪

  • 设计模式——组合模式(Composite)
            
    
    博客分类: 设计模式 组合模式composite模式java设计模式 
  • 大小: 4.2 KB
  • 设计模式——组合模式(Composite)
            
    
    博客分类: 设计模式 组合模式composite模式java设计模式 
  • 大小: 752 Bytes