设计模式之美:Composite(组合)
索引
意图
将对象组合成树形结构以表示 “部分-整体” 的层次结构。
Composite 使得用户对于单个对象和组合对象的使用具有一致性。
Compose objects into tree structures to represent part-whole hierarchies.
Composite lets clients treat individual objects and compositions of objects uniformly.
结构

典型的 Composite 对象结构:

参与者
Component
- 为组合中的对象声明接口。
- 在适当的情况下,实现所有类共有接口的缺省行为
- 声明一个接口用于访问和管理 Component 的子组件。
- 在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
Leaf
- 在组合中表示叶节点对象,叶节点没有子节点。
- 在组合中定义图元对象的行为。
Composite
- 定义有子部件的那些部件的行为。
- 在 Composite 接口中实现与子部件有关的操作。
Client
- 通过 Component 接口操纵组合部件的对象。
适用性
在以下情况下可以使用 Composite 模式:
- 你想表示对象的 “部分-整体” 层次结构。
- 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
缺点
- 与类层次结构设计原则冲突
Composite 模式的目的之一是使得用户不知道它们正在使用具体的 Leaf 和 Composite 类。
为达到这一目的,Component 需要为 Leaf 和 Composite 定义一些公共操作,并提供缺省的实现,而 Leaf 和 Composite 子类可以对它们进行重定义。
然而,这个目标会与类层次结构设计原则冲突,该原则规定:一个类只能定义那些对它的子类有意义的操作。
效果
- 定义了包含基本对象和组合对象的类层次结构。
- 简化客户代码。
- 使得更容易增加新类型的组件。
- 使你的设计变得更加一般化。
相关模式
- Command 模式描述了如何用一个 MacroCommand Composite 类组成一些 Command 对象,并对它们进行排序。
- 通常 “部件-父部件” 连接用于 Responsibility of Chain 模式。
- Decorator 模式经常与 Composite 模式一起使用。它们通常有一个公共的父类。
- Flyweight 让你共享组件,但不再能引用它们的父部件。
- Iterator 可以用来遍历 Composite。
- Visitor 将本来应该分布在 Composite 和 Leaf 类中的操作和行为局部化。
实现
实现方式(一):在 Component 中定义公共接口以保持透明性但损失安全性。
在 Component 中定义 Add 和 Remove 操作需要考虑安全性和透明性。
在类层次结构的根部定义子节点管理接口的方法具有良好的透明性,但是这一方法是以安全性为代价的,因为客户有可能会做一些无意义的事情,例如在 Leaf 中 Add 对象等。
在 Composite 类中定义管理子部件的方法具有良好的安全性,但是这又损失了透明性,因为 Leaf 和 Composite 具有不同的接口。
namespace CompositePattern.Implementation1
{
public abstract class Component
{
protected List<Component> _children = new List<Component>(); public abstract void Operation(); public virtual void Add(Component component)
{
_children.Add(component);
} public virtual void Remove(Component component)
{
_children.Remove(component);
} public virtual IEnumerable<Component> GetChildren()
{
return _children;
}
} public class Leaf : Component
{
public override void Operation()
{
// do something
} public override void Add(Component component)
{
throw new InvalidOperationException();
} public override void Remove(Component component)
{
throw new InvalidOperationException();
} public override IEnumerable<Component> GetChildren()
{
throw new InvalidOperationException();
}
} public class Composite : Component
{
public override void Operation()
{
foreach (var child in _children)
{
child.Operation();
}
// may do something
}
} public class Client
{
public void TestCase1()
{
Component component1 = new Leaf();
Component component2 = new Composite(); component2.Add(component1); component1.Operation();
component2.Operation();
}
}
}
《设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。
设计模式之美:Composite(组合)的更多相关文章
- 设计模式08: Composite 组合模式(结构型模式)
Composite 组合模式(结构型模式) 对象容器的问题在面向对象系统中,我们常会遇到一类具有“容器”特征的对象——即他们在充当对象的同时,又是其他对象的容器. public interface I ...
- 设计模式学习笔记——Composite 组合模式
用于描述无限层级的复杂对象,类似于描述资源管理器,抽象出每一个层级的共同特点(文件夹和文件,展开事件) 以前描述一个对象,是将整个对象的全部数据都描述清楚,而组合模式通过在对象中定义自己,描述自己的下 ...
- 设计模式(七)组合模式Composite(结构型)
设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 ...
- Ruby设计模式透析之 —— 组合(Composite)
转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/9153761 此为Java设计模式透析的拷贝版,专门为Ruby爱好者提供的,不熟悉R ...
- Java设计模式(8)组合模式(Composite模式)
Composite定义:将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到Composite就应该想到树 ...
- 一天一个设计模式——Composite组合模式
一.模式说明 能够使容器与内容物具有一致性,创造出递归结构的模式就是Composite组合模式. 举个例子:计算机中的文件系统中有文件和文件夹的概念,我们知道,文件夹可以包含文件,也可以包含子文件夹, ...
- C++设计模式-Composite组合模式
Composite组合模式作用:将对象组合成树形结构以表示“部分-整体”的层次结构.Composite使得用户对单个对象和组合对象的使用具有一致性. UML图如下: 在Component中声明所有用来 ...
- 设计模式之美:Structural Patterns(结构型模式)
结构型模式涉及到如何组合类和对象以获得更大的结构. 结构型类模式采用继承机制来组合接口实现. 结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法. 因为 ...
- 设计模式之美:Prototype(原型)
索引 别名 意图 结构 参与者 适用性 缺点 效果 相关模式 命名约定 实现 实现方式(一):使用一个原型管理器. 实现方式(二):使用浅拷贝实现克隆(Clone)操作. 实现方式(三):使用深拷贝实 ...
随机推荐
- linux shell学习笔记
一 变量 声明变量: my_var='ddd'使用变量: ${my_var}设置为只读变量: readonly my_var删除变量: unset my_var 注意只读变量不能被删除 变量类型:( ...
- 为什么 1KB = 1024Byte???群里讨论。
- Django web 基础
一.Django概述 Django大而全; 创建Django工程:django-admin startproject sitename 创建django之后生成的目录结构如下: Project Pro ...
- 易语言软件加VMProtect壳的正确方法
VMP是一款很强大的加密壳,代码虚拟化技术可以很好的保护程序不被恶意修改破J但是很多人不知道怎么给自己的程序加壳,今天给大家晋级下加壳的正确方法 相信很多新手都以为只要把软件直接拖到VMP里重新编译一 ...
- java.util.Date和java.sql.Date的区别和相互转化(转)
java.util.Date是在除了SQL语句的情况下面使用的.java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分它们都有getTime方法返回毫秒数,自然就可以直接构建. ...
- Java NIO教程 MappedByteBuffer
之前跟大家说过,要讲MappedByteBuffer,现在我来履行承诺了. 首先从大体上讲一下MappedByteBuffer究竟是什么.从继承结构上来讲,MappedByteBuffer继承自Byt ...
- php 处理别人直接丢过来的json字符串
如果 json校验成功 出现莫名其妙的不能decode 就看下转义 最好是直接使用php定界符eof来赋值字符串
- linux shell 去重 uniq和sort的区别
sort -u 和 uniq都能起到删除重复信息的功能,那么他们的区别究竟在哪呢?$ cat test jasonjasonjasonfffffjason 下面分别执行三个命 ...
- a==null和a.equals("null")的区别
equals 是值比较,==是比较内存 A==B,比较句柄,就是比较变量A,B的地址存放的东西,比如int A=0;String B="bbbb";那么变量A的地址方的就是0,B的 ...
- System.IO.Directory类
1.参考的博客:System.IO.Directory类和System.DirectoryInfo类(http://blog.sina.com.cn/s/blog_614f473101017du4.h ...