重修设计模式-结构型-组合模式
Compose objects into tree structure to represent part-whole hierarchies.Composite lets client treat individual objects and compositions of objects uniformly.
将一组对象组织成树形结构,来表示一种"部分 - 整体"的层次结构。组合让客户端可以统一单个对象和组合对象的处理逻辑。
组合模式(Composite Pattern)也叫部分-整体模式(Part-Whole), 用来描述部分与整体的关系,主要是用于处理树形结构数据。
组合模式的三个角色
-
组件抽象接口(Component)
定义一些参加组合对象的通用行为或属性。
-
叶子节点(Leaf)
表示叶子节点对象,下面没有其他分支,是遍历的最小单位。
-
组合节点(Composite)
表示有子节点的对象,作用是组合树枝节点和叶子节点形成一个树形结构。
举个例子,在程序中表示下图的公司组织架构,并可计算总薪资情况:
其中员工是叶子节点;部门是组合节点,包含子部门和员工,是一种嵌套结构,可以表示成树这种数据结构。计算每个部门的薪资开支这样一个需求,也可以通过在树上的遍历算法来实现。用组合模式实现如下:
kotlin
//组件抽象接口
abstract class CompanyInfo(val name: String) {
abstract fun calculateSalary(): Double
}
//组合节点
class Department(name: String): CompanyInfo(name) {
private val mHumanList = mutableListOf<CompanyInfo>()
override fun calculateSalary(): Double {
return mHumanList.sumOf { it.calculateSalary() } //部门薪资是所有子节点的薪资总和
}
fun addNode(info: CompanyInfo) {
}
fun removeNode(name: String) {
}
}
//叶子节点
class Employee(name: String, private val salary: Double) : CompanyInfo(name) {
override fun calculateSalary(): Double {
return salary //员工薪资就是自己的
}
}
调用处:
kotlin
fun main() {
val root = buildCompany() //只需处理CompanyInfo类型,不关心子类型
val totalSalary = root.calculateSalary()
println("${root.name}总薪资:${totalSalary}")
}
fun buildCompany(): CompanyInfo {
val rootCompany = Department("技术有限公司")
val department1 = Department("研发部")
department1.addNode(Employee("老大", 2000.0))
department1.addNode(Employee("老三", 1500.0))
department1.addNode(Employee("老六", 1000.0))
rootCompany.addNode(department1)
val department2 = Department("行政部")
department2.addNode(Employee("大美", 3000.0))
department2.addNode(Employee("小丽", 2500.0))
department2.addNode(Employee("小舞", 2000.0))
val childDepartment = Department("法务部")
childDepartment.addNode(Employee("硬币", 10000.0))
department2.addNode(childDepartment)
rootCompany.addNode(department2)
return rootCompany
}
调用时可以一致地使用组合或单个对象,不需要区分叶子节点还是组合节点。并且增加新的组合对象很容易,只需要实现组件抽象接口,不需要修改原有代码,这就是组合模式的特点。
总结
组合模式的设计思路,更像对业务场景的一种数据结构和算法的抽象。其中,数据可以表示成树这种数据结构,业务需求可以通过在树上的递归遍历算法来实现。使用组合模式的前提在于,业务场景必须能够表示成树形结构。所以组合模式的应用场景也比较局限,并不是一种很常用的设计模式。