本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
其他设计模式介绍
创建型:
工厂方法
抽象工厂
原型
结构型:
适配器
桥接模式
组合模式
装饰模式
外观模式
享元模式
代理模式
行为型:
职责链
命令
解释器
迭代器
中介者
备忘录
状态模式
策略模式
模板方法
访问者
定义
-
组合模式实际上就是个树形结构,一棵树的节点如果没有分支,就是叶子节点;如果存在分支,则是树枝节点。
-
我们平时遇到的最典型的组合结构就是文件和文件夹了,具体的文件就是叶子节点,而文件夹下还可以存在文件和文件夹,所以文件夹一般是树枝节点。
-
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性
UML
模式的结构
组合模式包含以下主要角色。
-
抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
-
树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。
-
树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
示例
//抽象构件
internal interface Component {
fun add(c: Component)
fun remove(c: Component)
fun getChild(i: Int): Component?
fun operation()
}
//树叶构件
internal class Leaf(private val name: String) : Component {
override fun add(c: Component) {}
override fun remove(c: Component) {}
override fun getChild(i: Int): Component? {
return null
}
override fun operation() {
println("树叶$name:被访问!")
}
}
//树枝构件
internal class Composite : Component {
private val children = ArrayList<Component>()
override fun add(c: Component) {
children.add(c)
}
override fun remove(c: Component) {
children.remove(c)
}
override fun getChild(i: Int): Component? {
return children[i]
}
override fun operation() {
for (obj in children) {
obj.operation()
}
}
}
fun main() {
val c0: Component = Composite()
val c1: Component = Composite()
val leaf1: Component = Leaf("1")
val leaf2: Component = Leaf("2")
val leaf3: Component = Leaf("3")
c0.add(leaf1)
c0.add(c1)
c1.add(leaf2)
c1.add(leaf3)
c0.operation()
}
程序运行结果如下:
树叶1:被访问!
树叶2:被访问!
树叶3:被访问!
组合模式的应用场景
前面分析了组合模式的结构与特点,下面分析它适用的以下应用场景。
- 需要表示一个对象整体或部分层次,在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,可以一致地对待它们。
- 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
- 让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无须关心对象层次结构的细节。
小结
-
组合模式用于将多个对象组合成树形结构以表示“整体-部分”的结构层次。组合模式对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。
-
组合对象的关键在于它定义了一个抽象构建类,它既可表示叶子对象,也可表示容器对象,客户仅仅需要针对这个抽象构建进行编程,无须知道他是叶子对象还是容器对象,都是一致对待。
-
组合模式虽然能够非常好地处理层次结构,也使得客户端程序变得简单,但是它也使得设计变得更加抽象,而且也很难对容器中的构件类型进行限制,这会导致在增加新的构件时会产生一些问题。