设计模式之组合模式
引例
在现实生活中,存在很多“部分-整体”的关系,例如,大学中的学院与系、总公司中的分公司与部门,文件系统中的文件与文件夹等。对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。
组合模式介绍
组合模式定义如下:
组合模式(Composite Pattern)也称为整体部分(Part-Whole)模式 ,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示 ,使得客户对单个对象和组合对象的使用具有一致性 ,属于结构型模式。
由上图可以看出,其实根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用;而叶子节点与树枝节点在语义上不属于用一种类型。但是在组合模式中,会把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让它们具备一致行为。
uml类图
在组合模式结构图中包含如下几个角色:
-
Component(抽象构件)
它可以是接口或抽象类,为叶子构件和树枝构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,如增加子构件、删除子构件、获取子构件等。
-
Composite(树枝构件)
它在组合结构中表示树枝节点对象,树枝节点包含子节点,其子节点可以是叶子节点,也可以是树枝节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。
-
Leaf(叶子构件)
它在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。
代码实现
假设现在需要编写程序展示一个学校院系结构,展示出学校的院系组成,一个学校有多个学院,一个学院有多个系。并可以对学院,系进行添加,删除等管理操作。
1、抽象构件
package day09_composite.test01;
/**
* @author coolsheep
* @date 2023/4/11 9:44
* @Describe 抽象构建
*/
public interface SchoolComponent {
//添加子构件
void add(SchoolComponent schoolComponent);
//删除子构件
void remove(SchoolComponent schoolComponent);
//打印输出信息
void print();
}
树枝构件
package day09_composite.test01;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author coolsheep
* @date 2023/4/11 9:50
* @Describe 学校-树枝构件
*/
@Data
public class University implements SchoolComponent{
private String name;
public University(String name) {
this.name = name;
}
private List<SchoolComponent> schoolComponents = new ArrayList<>();
@Override
public void add(SchoolComponent schoolComponent) {
schoolComponents.add(schoolComponent);
}
@Override
public void remove(SchoolComponent schoolComponent) {
schoolComponents.remove(schoolComponent);
}
@Override
public void print() {
System.out.println("=============="+getName()+"================");
for (SchoolComponent schoolComponent : schoolComponents) {
schoolComponent.print();
}
}
}
package day09_composite.test01;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author coolsheep
* @date 2023/4/11 9:50
* @Describe 学院-树枝构件
*/
@Data
public class college implements SchoolComponent{
private String name;
public college(String name) {
this.name = name;
}
private List<SchoolComponent> schoolComponents = new ArrayList<>();
@Override
public void add(SchoolComponent schoolComponent) {
schoolComponents.add(schoolComponent);
}
@Override
public void remove(SchoolComponent schoolComponent) {
schoolComponents.remove(schoolComponent);
}
@Override
public void print() {
System.out.println("=============="+getName()+"================");
for (SchoolComponent schoolComponent : schoolComponents) {
schoolComponent.print();
}
}
}
叶子构建
package day09_composite.test01;
import lombok.Data;
/**
* @author coolsheep
* @date 2023/4/11 10:20
* @Describe
*/
@Data
public class department implements SchoolComponent{
private String name;
public department(String name) {
this.name = name;
}
@Override
public void add(SchoolComponent schoolComponent) {
throw new UnsupportedOperationException();
}
@Override
public void remove(SchoolComponent schoolComponent) {
throw new UnsupportedOperationException();
}
@Override
public void print() {
System.out.println(getName());
}
}
组合模式的应用场景
-
在需要表示一个对象整体与部分的层次结构的场合。
-
要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
比如树形菜单,操作系统目录结构,公司组织架构等。