一 定义
将对象组合呈树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
比如,总公司下设总公司行政部、总公司研发部和子公司,而子公司又下设子公司行政部和子公司研发部。
(1)表示对象的部分-整体层次结构时;
(2)从一个整体中能够独立出部分模块或功能的场景。
三 UML类图
角色说明:
- Component(抽象组件角色):定义参加组合对象的共有方法和属性,可以定义一些默认的函数或属性。
- Leaf(叶子节点):叶子没有子节点,因此是组合树的最小构建单元。
- Composite(树枝节点):定义所有枝干节点的行为,存储子节点,实现相关操作。
四 代码实例
4.1 抽象根节点:为组合中的对象声明接口
interface Component {
var name: String?
val TAG: String
get() = "Component"
fun doSomething()
fun addChild(child:Component)
fun removeChild(child:Component)
fun getChildren(index:Int):Component
}
4.2 具体枝干节点:定义有子节点的那些枝干节点的行为,存储子节点
class Composite(override var name:String?) : Component{
var components = ArrayList<Component>()
override fun doSomething() {
Log.d(TAG,name!!)
for (c in components){
c.doSomething()
}
}
override fun addChild(child:Component) {
components.add(child)
}
override fun removeChild(child:Component) {
components.remove(child)
}
override fun getChildren(index:Int):Component{
return components.get(index)
}
}
4.3 具体叶子节点:叶子节点没有子节点,在组合中定义节点对象的行为
class Leaf(override var name:String?) : Component {
override fun doSomething() {
Log.d(TAG,name!!)
}
override fun addChild(child: Component) {
throw UnsupportedOperationException("叶子没有节点")
}
override fun removeChild(child: Component) {
throw UnsupportedOperationException("叶子没有节点")
}
override fun getChildren(index: Int): Component {
throw UnsupportedOperationException("叶子没有节点")
}
}
4.3 客户类:通过Component接口操纵组合节点的对象
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var root = Composite("Root")
var branch1 = Composite("branch1")
var branch2 = Composite("branch2")
var leaf1 = Leaf("Leaf1")
var leaf2 = Leaf("Leaf2")
branch1.addChild(leaf1)
branch2.addChild(leaf2)
root.addChild(branch1)
root.addChild(branch2)
root.doSomething()
}
五 优缺点
组合模式在Android中最经典的实现就是View和ViewGrounp的嵌套组合。当然这种模式真正需要开发者去实现的并不多。
5.1 优点
- 可以清楚的定义分层次的复杂对象,表示对象的全部或部分层次,它让高层模块忽略了层次的差异,方便对整个层次结构进行控制;
- 高层模块可以一致的使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了高层模块的代码;
- 在组合模式中增加新的枝干构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”;
- 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和枝干对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。
5.2 缺点
在新增构件时不好对枝干中的构件类型进行限制,不能依赖类型系统来施加这些约束,因为在大多数情况下,它们都来自于相同的抽象层,此时,必须及时进行类型检查来实现,这个实现过程较为复杂。
六 Android 源码中的应用
1.文件和文件夹
2.view和ViewGrounp就是典型的组合模式