type
status
date
slug
summary
tags
category
icon
password
comment_flag
SLUGS
目的
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
动机
在绘图编辑器和图形捕捉系统这样的图形应用系统中,用户可以使用简单的组件创建复杂的图标。用户可以组合多个简单组件以形成一些较大的组件,这些组件又可以组合成更大的组件。一个简单的实现方法是为Text和Line这样的图元定义一些类,另外定义一些类作为这些图元的容器类(Container)。
然而这种方法存在一个问题:使用这些类的代码必须区别对待图元对象与容器对象,而实际上大多数情况下用户认为它们是一样的。对这些类区别对待,使得程序更加复杂。Composite模式描述了如何使用递归组合,使得用户不比对这些类进行区别,如下图:
好处
- 一些部件对象经过组合构成的复合部件对象仍然具有单个部件对象的接口,这样的复合部件对象称为“容器(Container)”
- 复合部件与单个部件具有同样的接口,所有接口包含两部分:单个部件的功能、管理子部件的功能
- 实现递归组合
模式的结构
组合模式结构如上图所示,
其包含以下主要角色:
- 抽象构件(Component)角色:它的
主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为
。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
- 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,
用于实现抽象构件角色中声明的公共接口
。
- 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它
实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件
,通常包含Add()
、Remove()
、GetChild()
等方法。
- 客户端(Client)角色:调用抽象构建接口的方法。
组合方式分类
- 透明式组合方式:在该方式中,由于抽象构建声明了所有子类中的全部方法,所以客户端无需区别树叶对象和树枝对象,对客户端来说是透明的。缺点是:树叶构建本来没有
add()
、remove()
及getChild()
等方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。
- 安全式组合方式:在该方式中,将管理自购件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题。但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。
适用范围
- 想要表示对象的部分-整体层次结构
- 希望用户忽略组合对象和单个对象的不同,用户将统一地使用组合结构中的所有对象
评价
- 定义了包含leaf对象和composite对象的类层次接口,是一种递归结构
- 客户一致地处理复合对象和单个对象。
- 易于增加新类型的组件。
- 容易增加新组件也会带来问题:很难限制组合中的组件。有时希望一个组合只能有某些特定的组件,使用Composite时,不能依赖类型系统施加的这些约束,而必须在运行时刻进行检查。
实现见后文。
参考文章: