设计模式(8)--组合模式

数据结构中有一种结构是树,树包含根节点、子节点、叶子结点,而组合模式就是专门用来处理类似树结构的设计模式,组成这棵树的节点和叶子是一个个对象,而组合模式却可以以统一对待叶子和节点。

要想统一对待,在面向对象中很难不想到抽象二字,只有站的高,面向高层处理,才有底气屏蔽底层细节,增加扩展性。

举个栗子:

   平常我们用的windows文件夹就是树结构的,文件夹里可以包含文件夹,文件夹里可以包含文件,这里文件夹代表容器,也就是节点,文件就代表叶子结点,不可包含其他。


组合模式UML类图如下所示:


解释:Folder和File_是Compotent的子类容易理解,但但Component和Folder的关联聚合关系怎么理解呢?Component是Folder和File_的抽象,但在这个树状结构中,Folder既能包含Folder,又能包含File_,也就是Folder包含他们的共同父类Component:Folder contains Conponent,体现在类图中的就是聚合关系。


下面以读取文件夹为例写一个组合模式实例小程序,注意读取文件夹会把他下面所有文件夹带文件读取一遍。

抽象组件类:

/****
 * 抽象组件类,文件夹和文件的抽象类
 * @author wjw
 *
 */
public abstract class Component {

	public abstract void addComponent(Component component);
	public abstract void deleteComponent(Component component);
	public abstract Component getChild(int i);
	public abstract void read();
}

文件夹类:


public class Folder extends Component{
	private String folderName;
	private List<Component> components = new ArrayList<Component>();
	public Folder(String folderName){
		this.folderName = folderName;
	}
	@Override
	public void addComponent(Component component) {
		// TODO Auto-generated method stub
		components.add(component);
	}

	@Override
	public void deleteComponent(Component component) {
		// TODO Auto-generated method stub
		components.remove(component);
	}

	@Override
	public Component getChild(int i) {
		// TODO Auto-generated method stub
		return components.get(i);
	}

	@Override
	public void read() {
		// TODO Auto-generated method stub
		System.out.println("读取=="+folderName+"==文件夹!");
		System.out.println("----begin "+folderName+"----");
		for (Component component : components) {
			component.read();
		}
		System.out.println("----end "+folderName+"----");
	}

}

文件类:

public class File_ extends Component{

	private String fileName;
	public File_(String fileName){
		this.fileName = fileName;
	}
	@Override
	public void addComponent(Component component) {
		// TODO Auto-generated method stub
		System.out.println("文件中不允许添加文件!");
	}

	@Override
	public void deleteComponent(Component component) {
		// TODO Auto-generated method stub
		System.out.println("文件中不允许删除文件!");
	}

	@Override
	public Component getChild(int i) {
		// TODO Auto-generated method stub
		System.out.println("文件中不允许读取文件!");
		return null;
	}

	@Override
	public void read() {
		// TODO Auto-generated method stub
		System.out.println("读取--"+fileName+"--文件!");
	}

}

Main类:

public class Main {


	public static void main(String[] args) {
		Component c1 = new Folder("C盘");
		Component c2 = new Folder("系统文件夹");
		Component c3 = new Folder("应用程序文件夹");
		Component c3_1 = new Folder("QQ文件夹");
		Component c3_2 = new Folder("MYSQL文件夹");
		Component c3_3 = new Folder("MSN文件夹");
		Component c4 = new Folder("资料文件夹");
		Component c4_1 = new Folder("音乐文件夹");
		Component c4_1_1 = new File_("海阔天空.mp3");
		Component c4_2 = new Folder("图片文件夹");
		Component c4_2_1 = new File_("aaa.jpg");
		Component c4_2_2 = new File_("bbb.png");
		c1.addComponent(c2);
		c1.addComponent(c3);
		c1.addComponent(c4);
		c3.addComponent(c3_1);
		c3.addComponent(c3_2);
		c3.addComponent(c3_3);
		c4.addComponent(c4_1);
		c4.addComponent(c4_2);
		c4_1.addComponent(c4_1_1);
		c4_2.addComponent(c4_2_1);
		c4_2.addComponent(c4_2_2);
		
		c1.read();
	}
}


运行结果:

读取==C盘==文件夹!
----begin C盘----
读取==系统文件夹==文件夹!
----begin 系统文件夹----
----end 系统文件夹----
读取==应用程序文件夹==文件夹!
----begin 应用程序文件夹----
读取==QQ文件夹==文件夹!
----begin QQ文件夹----
----end QQ文件夹----
读取==MYSQL文件夹==文件夹!
----begin MYSQL文件夹----
----end MYSQL文件夹----
读取==MSN文件夹==文件夹!
----begin MSN文件夹----
----end MSN文件夹----
----end 应用程序文件夹----
读取==资料文件夹==文件夹!
----begin 资料文件夹----
读取==音乐文件夹==文件夹!
----begin 音乐文件夹----
读取--海阔天空.mp3--文件!
----end 音乐文件夹----
读取==图片文件夹==文件夹!
----begin 图片文件夹----
读取--aaa.jpg--文件!
读取--bbb.png--文件!
----end 图片文件夹----
----end 资料文件夹----
----end C盘----


组合模式说明:

如果我们程序要处理的是一个树形结构,且忽略整体与部分差异,可以考虑组合模式合适不合适。这里我们组件就两个,分的不太细,在具体编程中,也许组件种类很多,比如文件夹类型分为系统文件夹,普通文件夹,文件类型分为图片文件、文本文件、音频文件、视频文件等。这时我们面向抽象的优点再次显现出来了。对扩展开放。

总而言之,组合模式处理树


如有错误,欢迎指正

end


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值