组合模式

一、组合模式概述

  组合模式是用面向对象的方式来组合多个对象形成树形结构以表示“整体—部分”的结构层次,它对单个对象(叶子对象)和组合对象(容器对象)的操作具有一致性。其核心类是一个抽象类,通常这个类是整个模式中所有类的父类。下面是一个一般的文件目录树形结构图,组合模式就是用来操作管理类似的具有树形结构的对象组合的。


在组合模式中有叶子构件和容器构件两种构件,叶子构件中不能包含成员对象,而容器构件可以包含成员对象,就像上面的文件目录结构一样,文件夹相当于容器构件,文件相当于叶子构件,所以文件夹中即可以包含文件夹,也可以包含文件,而文件是最终的叶子构件,它不能再包含文件夹或文件。组合模式为叶子构件和容器构件提供了一个公共的抽象构件类,客户端可以针对该抽象类进行处理,而无须关心所操作的是哪种类型的对象。组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区别,可以一致地对待容器对象和叶子对象。

下图是一个典型的组合模式的结构图


从这个结构图上可以看到,组合模式主要包含以下角色:

1、Component(抽象构件):抽象构件为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现,在此构件中定义了访问及管理它的子构件的方法。2、Leaf(叶子构件):叶子构件没有子节点,它实现了在抽象构件中定义的行为。

3、Composite(容器构件):它表示容器节点对象,其子节点可以是叶子结点,也可以是容器节点,它提供了一个用于存储子节点的集合。

4、客户将通过抽象构件的接口访问和控制组合构件中的对象。

 

二、组合模式实例

  文件有不同的类型,不同类型的文件的浏览方式是不同的,如对文件夹的浏览其实是对文件夹内所包含文件的浏览,而对具体文件的浏览则是对文件本身内容的浏览。下面用组合模式来模拟文件浏览的操作。为了便于描述问题,我只设计了一个简单的类图


下面是这个类图对应的代码

1.      AbstractFile类,这是一个抽象类,即抽象构件类,它描述各种文件共有的操作方法

public abstract class AbstractFile {
	public abstract void add(AbstractFile element);
	public abstract void remove(AbstractFile element);
	public abstract void display();
}

2.      ImageFile类,叶子构件类,实现图像文件的相关操作

public class ImageFile extends AbstractFile {

	@Override
	public void add(AbstractFile elment) {
		System.out.println("   An image file is added");
	}

	@Override
	public void remove(AbstractFile element) {
		System.out.println("   An image file is removed");
	}

	@Override
	public void display() {
		System.out.println("   An image file is displayed");
	}
}

3.      VideoFile类,叶子构件类,实现视频文件的相关操作

public class VideoFile extends AbstractFile {

	@Override
	public void add(AbstractFile elment) {
		System.out.println("   An video file is added");
	}

	@Override
	public void remove(AbstractFile element) {
		System.out.println("   An video file is removed");
	}

	@Override
	public void display() {
		System.out.println("   An video file is displayed");
	}
}

4.      Folder类,容器构件类,实现文件夹的相关操作

public class Folder extends AbstractFile {
	
	private ArrayList<AbstractFile> fileList = new ArrayList<AbstractFile>();
	private String fileName;
	
	Folder(String fileName)
	{
		this.fileName = fileName;
	}

	@Override
	public void add(AbstractFile element) {
		fileList.add(element);
	}

	@Override
	public void remove(AbstractFile element) {
		fileList.remove(element);
	}

	@Override
	public void display() {
		for(Object obj:fileList)
		{
			System.out.print(fileName);
			((AbstractFile)obj).display();
		}
	}
}

5.      Client类,客户端测试类

public class ClientTest {
	public static void main(String argv[])
	{
		AbstractFile afile1, afile2, afile3, afile4, afile5;
		Folder folder1, folder2, folder3;
		
		afile1 = new ImageFile();
		afile2 = new VideoFile();
		folder1 = new Folder("   folder1 ");
		folder1.add(afile1);
		folder1.add(afile2);
		
		afile3 = new ImageFile();
		afile4 = new VideoFile();
		folder2 = new Folder("   folder2 ");
		folder2.add(afile3);
		folder2.add(afile4);
		
		afile5 = new VideoFile();
		folder3 = new Folder("folder3\n");
		folder3.add(folder1);
		folder3.add(folder2);
		folder3.add(afile5);
		
		folder3.display();
		System.out.println("\n--------------Remove folder1--------------\n");
		folder3.remove(folder1);
		folder3.display();
	}
}

下面是客户端测试类在第一次调用display()函数前所构建出来的文件目录结构

三、小结

组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件更容易;客户端可以一致地使用组合结构或其中单个对象,而不必关心自己处理的是单个对象还是整个组合结构;在组合体内加入新的对象构件很方便。但是组合模式使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式是很困难的,而且不是所有的方法都与叶子对象子类有关联;增加新构件时很难对容器中的构件类型进行限制。




  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Storm-Shadow

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值