设计模式8:组合模式

组合模式

定义:将对象组合成树形结构,表示层次结构关系,并且让对象能够以同样的方式呈现给客户端程序。

在前面几篇介绍代理模式,桥接模式等模式的时候,我都会先举个实际场景,然后先介绍一种解决方案,接着指出这种方案的不足之处,最后再引出我们的xxx模式。但是我们接下来的组合模式就不采取这种讲解模式啦,因为它要解决的场景基本上没有其他的用来反衬的方案啦。

记住一点,凡是碰到有树形结构的关系的场景,基本上就用组合模式没跑啦。

我们操作系统中的文件夹结构,就是典型的树状结构

主要角色

  • Component :组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。 
  • Leaf:叶子对象。叶子结点没有子结点。 
  • Composite:容器对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。

工作流程

既然我们提到组合模式是为了解决树状结构而生的,那么它究竟是如何解决的呢?由于我们的容器对象和叶子对象都实现了一个共同的Component接口,并都实现了接口里定义的一系列操作节点的方法,并且每个容器里有一个arrayList用来存储它的子节点(可以是叶子对象也可以是容器对象),当容器对象的指定方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员,并调用执行。其中,使用了递归调用的机制对整个结构进行处理。

如果前面解释的不是很清楚的话,接下来我们来看一个具体的实例,来模仿一个杀毒软件的设计

实例

让我们来梳理下一个杀毒软件是如何工作的,首先它肯定要对某个文件夹进行扫描,在该文件夹内,如果碰到图片、文本、视频文件等(即叶子对象),则直接对其处理,若是遇到子文件夹(容器对象),则对其递归处理...嗯,大致是这样的..是一个典型的树状结构

首先定义一个抽象构造,即Component接口

//抽象构建
public interface AbstractFile {
	void killVirus();  //杀毒
}

接下来分别定义具体的图片、文本、视频的杀毒处理,即叶子对象,都要实现抽象构造接口

class ImageFile implements AbstractFile {
	private String name;
	
	public ImageFile(String name) {
		super();
		this.name = name;
	}

	@Override
	public void killVirus() {
		System.out.println("---图像文件:"+name+",进行查杀!");
	}
	
}
class TextFile implements AbstractFile {
	private String name;
	
	public TextFile(String name) {
		super();
		this.name = name;
	}
	
	@Override
	public void killVirus() {
		System.out.println("---文本文件:"+name+",进行查杀!");
	}
}
class VideoFile implements AbstractFile {
	private String name;
	
	public VideoFile(String name) {
		super();
		this.name = name;
	}
	
	@Override
	public void killVirus() {
		System.out.println("---视频文件:"+name+",进行查杀!");
	}
}

接着再定义文件夹类,该类中增加add,remove方法以及一个用来存储子节点的arrayList对象。在杀毒方法中,对所有子节点进行遍历,然后调用每个节点的杀毒方法(递归形成)

class Folder implements AbstractFile {
	private String name;
	//定义容器,用来存放本容器构建下的子节点
	private List<AbstractFile> list = new ArrayList<AbstractFile>();
	
	public Folder(String name) {
		super();
		this.name = name;
	}

	public void add(AbstractFile file){
		list.add(file);
	}
	public void remove(AbstractFile file){
		list.remove(file);
	}
	public AbstractFile getChild(int index){
		return list.get(index);
	}

	@Override
	public void killVirus() {
		System.out.println("---文件夹:"+name+",进行查杀");
		
		for (AbstractFile file : list) {
			file.killVirus();
		}
		
	}
	
}

客户端测试

public class Client {
	public static void main(String[] args) {
		AbstractFile f2,f3,f4,f5;
		Folder f1 = new Folder("我的收藏");
		
		f2 = new ImageFile("老高的大头像.jpg");
		f3 = new TextFile("Hello.txt");
		f1.add(f2);
		f1.add(f3);
		
		Folder f11 = new Folder("电影");
		f4 = new VideoFile("笑傲江湖.avi");
		f5 = new VideoFile("神雕侠侣.avi");
		f11.add(f4);
		f11.add(f5);
		f1.add(f11);
		
		
//		f2.killVirus();
		
		f1.killVirus();	
	}
}

开发中的应用场景

凡是有树形结构的都可以用吧。。

  • 操作系统的资源管理器
  • GUI中的容器层次图
  • XML文件解析
  • OA系统中,组织结构的处理
  • Junit单元测试框架
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值