组合模式

1.组合模式是什么

1.百度百科

组合模式(Composite Pattern),将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分-整体” 还有 ”单个对象“ 与 "组合对象" 的含义。组合模式可以让客户端像修改配置文件一样简单的完成本来需要流程控制语句来完成的功能

2.维基百科

In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes a group of objects that is treated the same way as a single instance of the same type of object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.

3.lz理解

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

从定义中可以得到使用组合模式的环境为:在设计中想表示对象的“部分-整体”层次结构;希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象。

4.核心角色

抽象构件角色(Component):它可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,如增加子构件、删除子构件、获取子构件等。

叶子构件角色(Leaf):它在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。

容器构件角色(Composite):它在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。

客户端(Client):通过组件接口来操作组合结构里面的组件对象。

2.组合模式解决了什么问题

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

更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利!

3.组合模式用法

就拿创建文件和文件夹举例.
首先需要一个抽象构建角色,

package com.yanlong.CompositePattern.files;

public abstract class AbstractFile {

	private String name;

	public AbstractFile(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}


	public abstract void Add(AbstractFile abstractFile);

	public abstract void Remove(String fileName);

	public abstract void Display(int level);

}

叶子构件角色

public class File extends AbstractFile {


	public File(String name) {
		super(name);
	}

	@Override
	public void Add(AbstractFile file) {
		System.out.println("不能添加文件");

	}

	@Override
	public void Remove(String fileName) {
		System.out.println("不能添加文件夹");

	}

	@Override
	public void Display(int level) {
		StringBuilder sb = new StringBuilder("");
		for (int i = 0; i < level; i++) {
			sb.append(" - ");
		}
		System.out.println(new String(sb) + getName());
	}

}

容器构建角色


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class Folder extends AbstractFile {

	// private List<File> children = new ArrayList<File>();
	private Map<String, AbstractFile> children = new HashMap<String, AbstractFile>();

	public Folder(String name) {
		super(name);
	}

	@Override
	public void Add(AbstractFile file) {
		children.put(file.getName(), file);
	}

	@Override
	public void Remove(String fileName) {
		children.remove(fileName);

	}

	@Override
	public void Display(int level) {
		StringBuilder sb = new StringBuilder("");
		for (int i = 0; i < level; i++) {
			sb.append(" - ");
		}
		System.out.println(new String(sb) + getName());

		Iterator<Entry<String, AbstractFile>> e = children.entrySet().iterator();
		while (e.hasNext()) {

			e.next().getValue().Display(level + 1);

		}

	}

}

客户端调用


public class Client {

	public static void main(String[] args) {
		Folder root = new Folder("root");
		Folder music = new Folder("music");
		Folder document = new Folder("document");
		Folder resource = new Folder("resource");
		Folder movie = new Folder("movie");
		File guide = new File("guide");
		root.Add(music);
		root.Add(document);
		root.Add(resource);
		root.Add(movie);
		root.Add(guide);


		File smallMovie = new File("小电影.avi");
		movie.Add(smallMovie);


		File canon = new File("卡农.mp3");
		music.Add(canon);
		Folder classical = new Folder("古典音乐");
		music.Add(classical);
		File moonlight = new File("贝多芬-月光曲.mp3");
		classical.Add(moonlight);
		File nocturne = new File("肖邦-夜曲.mp3");
		classical.Add(nocturne);

		root.Display(0);
	}

}

root

  • music
    • 卡农.mp3
    • 古典音乐
      • 贝多芬-月光曲.mp3
      • 肖邦-夜曲.mp3
  • movie
    • 小电影.avi
  • resource
  • document
  • guide

文件和文件夹统一实现一个抽象的文件接口。统一了整体和部分的差异。使用客户端可以良好的调用。

4.组合模式的问题

叶子节点功能多余 容易造成叶子节点中许多功能不需要的情况,就是不容易限制组合中的构件。

5.组合模式总结

适用场景:

1 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们。
2 在一个使用面向对象语言开发的系统中需要处理一个树形结构。
3 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。

碎碎念:
组合模式最常用的地方就是树形结构存在的地方,比如文件夹-文件这样的需要提供一个统一的接口用来接收者两种类型的对象。从变化的角度来看实际上组合模式是封装了容器和文件的差异将其标准化在读取时方便好用。组合模式封装了其变化的结构使其变为稳定的结构这种封装类型也是比较独树一帜的。

引用

http://blog.csdn.net/ai92/article/details/298336

原文地址:https://www.cnblogs.com/yanlong300/p/8423546.html