持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情。
组合模式
简介
组合模式(Composite Pattern),又叫部分-整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
角色
- 抽象接口
- 叶子 单一对象,其内不组合
- 树枝 存在叶子或树枝组成的集合
例子
swing中的·组件·就是使用的组合模式,容器中可以有按钮、文字,并且都是组件。
Container里存在着多个Component可以是Label也可以是Button,那么Component就是一个树枝。
Label是一个文本组件,其内只存在文本属性,不会组合其他组件,那么他就是一个叶子。
公司组织结构的例子
组合模式适用于可以将关系抽象为一个树形结构的对象,从而实现良好的扩展性。
我们以公司结构说明
分公司下有许多部门,部门下有许多员工,那么这两个就是树枝节点。
员工下没有具体组织,那么普通员工就是叶子结点。
定义抽象接口:
public interface CompanyComponent {
//添加组件
Boolean addComponent(CompanyComponent companyComponent);
//移除组件
Boolean removeComponent(CompanyComponent companyComponent);
//遍历展示
void show(int depth);
}
组织(可能是分公司或是部门)
@Data
@AllArgsConstructor
public class DepartmentComponent implements CompanyComponent {
//组件名称
private String name;
//树枝节点下的叶子
public List<CompanyComponent> components;
@Override
public Boolean addComponent(CompanyComponent companyComponent) {
return components.add(companyComponent);
}
@Override
public Boolean removeComponent(CompanyComponent companyComponent) {
return components.remove(companyComponent);
}
@Override
public void show(int depth) {
//节点越深,等级越低
for (int i = 0; i < depth; i++) {
System.out.printf("-");
}
System.out.println(this.getName());
//递归遍历
components.forEach(companyComponent -> {
companyComponent.show(depth + 1);
});
}
}
员工
此时发现员工不需要实现抽象接口中的方法,其实此刻可以做接口拆分。
@Data
@AllArgsConstructor
public class EmployeeComponent implements CompanyComponent {
//组件名称
private String name;
@Override
public Boolean addComponent(CompanyComponent companyComponent) {
return false;
}
@Override
public Boolean removeComponent(CompanyComponent companyComponent) {
return true;
}
@Override
public void show(int depth) {
//节点越深,等级越低
for (int i = 0; i < depth; i++) {
System.out.printf("-");
}
System.out.println(this.getName());
}
}
测试
public class Client {
private static DepartmentComponent beijing;
static {
beijing = new DepartmentComponent("北京总公司", new ArrayList<>());
DepartmentComponent shanghai = new DepartmentComponent("上海分公司", new ArrayList<>());
DepartmentComponent wuhan = new DepartmentComponent("武汉分公司", new ArrayList<>());
DepartmentComponent suzhou = new DepartmentComponent("苏州分公司", new ArrayList<>());
DepartmentComponent hr = new DepartmentComponent("人事部门", new ArrayList<>());
DepartmentComponent fd = new DepartmentComponent("财务部门", new ArrayList<>());
DepartmentComponent td = new DepartmentComponent("技术部门", new ArrayList<>());
EmployeeComponent hrManager = new EmployeeComponent("人事经理");
EmployeeComponent employeeA = new EmployeeComponent("员工A");
EmployeeComponent employeeB = new EmployeeComponent("员工B");
EmployeeComponent manager = new EmployeeComponent("董事长");
hr.addComponent(hrManager);
hr.addComponent(employeeA);
hr.addComponent(employeeB);
//上海分公司下有
shanghai.addComponent(fd);
shanghai.addComponent(hr);
shanghai.addComponent(td);
beijing.addComponent(shanghai);
beijing.addComponent(suzhou);
beijing.addComponent(wuhan);
beijing.addComponent(manager);
}
public static void main(String[] args) {
System.out.println(beijing);
beijing.show(0);
}
}
数据会以树形结构存在
透明&安全
组合模式分透明模式和安全模式,以上的例子是透明模式的,对于Employee来说无需实现add 和 remove方法,我们实现了,是没有意义的。安全模式就是将add remove提到
组织中拓展,员工不用拓展。
应用
组合模式一般用于处理树形或存在层次结构的数据,其实java中对于树形结构的数据结构使用的就是组合模式。