JAVA设计模式之组合模式

1. 什么是组合模式?

《Head First设计模式》中定义:允许将对象组成树形结构来表现“整体-部分”的层次结构。组合模式能让客户以一致的方式处理个别对象和对象组合。


为了保持透明性,组合模式内部所有的对象都必须实现同一个接口,否则客户就必须操心哪个对象是用的哪个接口,这就失去了组合模式的意义。


组合模式又称为“整体-部分模式”,是一种对象结构型模式。

2. 角色

公共抽象组件(Component):为组合模式中的所有对象提供一个统一的接口。

叶子组件(Leaf):叶子组件没有孩子。实现Component接口中的部分方法。

容器组件(Composite):具有子节点,子节点可以是叶子节点也可以是容器节点。实现Component部分方法。

 

图片来源于《Head First设计模式》

 

3. 优点

(1)客户端可以一致的使用一个容器组件和叶子组件,不必关心两者之间的差别。

(2)组合模式中新增容器组件和叶子组件都无需更改原有代码,符合开闭原则。

(3)组合模式为树状数据结构提供了一种解决方案。

4. 缺点

    (1)无法限制组合组件中的子组件类型。在需要检测组件类型时,不能依靠编译期的类型约束来实现,必须在运行期间动态检测

5. 使用场景

(1)在具有整体和部分层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致对待。

(2)当需要使用树状数据结构时。

(3)当系统能够分离出叶子组件、容器组件,且他们的类型不固定,需要增加新的类型时。

6. 示例代码

模拟一个文件系统的实例。

(1)公共抽象组件Component

/**
 * 文件公共抽象类(相当于Component)
 */
public abstract class FileComponent {
	//文件名称
	private String fileName;
	
	public FileComponent(String fileName) {
		this.fileName=fileName;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	/**
	 * 打印文件名,index用来显示文件层级结构
	 */
	public abstract void display(String index);
	public abstract void add(FileComponent fileComponent);
	public abstract void delete(FileComponent fileComponent);
}

(2)叶子组件leaf

/**
 * 音乐文件类(相当于leaf)
 */
public class MusicFile extends FileComponent {

	public MusicFile(String fileName) {
		super(fileName);
	}

	@Override
	public void display(String index) {
		System.out.println(index+getFileName());
	}

	@Override
	public void add(FileComponent fileComponent) {
		//不支持此操作
		throw new UnsupportedOperationException();
	}

	@Override
	public void delete(FileComponent fileComponent) {
		//不支持此操作
		throw new UnsupportedOperationException();
	}
}

/**
 * 文本文件
 */
public class TxtFile extends FileComponent {

	public TxtFile(String fileName) {
		super(fileName);
	}

	@Override
	public void display(String index) {
		System.out.println(index+getFileName());
	}

	@Override
	public void add(FileComponent fileComponent) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void delete(FileComponent fileComponent) {
		throw new UnsupportedOperationException();
	}
}

(3) 容器组件 Composite

/**
 * 文件夹类(相当于Composite)
 */
public class Folder extends FileComponent {

	private List<FileComponent> fileList;
	
	public Folder(String fileName) {
		super(fileName);
		fileList=new ArrayList<FileComponent>();
	}

	@Override
	public void display(String index) {
		System.out.println(index+"Folder:"+getFileName());
		if(fileList!=null && fileList.size()>0){
			Iterator<FileComponent> iterator=fileList.iterator();
			while (iterator.hasNext()) {
				FileComponent file = (FileComponent) iterator.next();
				file.display(index+"--");
			}
		}
	}

	@Override
	public void add(FileComponent fileComponent) {
		fileList.add(fileComponent);
	}

	@Override
	public void delete(FileComponent fileComponent) {
		fileList.remove(fileComponent);
	}
}

(4)测试代码

public static void main(String[] args) {
		FileComponent fc=new Folder("音乐文件夹");
		fc.add(new MusicFile("死了都要爱.MP3"));
		fc.add(new MusicFile("四处漂泊.MP3"));
		FileComponent fc2=new Folder("歌词文件夹");
		fc2.add(new TxtFile("死了都要爱.txt"));
		fc2.add(new TxtFile("四处漂泊.txt"));
		fc.add(fc2);
		fc.display("");
		
		System.out.println("...............");
//删除子文件夹
		fc.delete(fc2);
		fc.display("");
}

(5)测试结果

Folder:音乐文件夹
--死了都要爱.MP3
--四处漂泊.MP3
--Folder:歌词文件夹
----死了都要爱.txt
----四处漂泊.txt
...............
Folder:音乐文件夹
--死了都要爱.MP3
--四处漂泊.MP3

【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值