又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示”整体-部分“层次。这种模式使得客户端可以统一处理单个对象和组合对象,而无需关心它们的具体实现。
核心角色
角色 |
职责 |
Component |
定义所有叶子和组合的公共接口,通常是抽象类或接口 |
Leaf |
表示没有子节点的对象,实现基本操作 |
Composite |
包含子组件的对象,实现容器行为,如添加、删除子组件等 |
适用场景
- 需要表示“整体-部分”关系的结构(如文件系统目录与文件、学校组织、管理层级)
- 希望客户端 以一致方式处理单个对象和组合对象。
- 结构具有层级性,并且可能动态变化。
真实案例
对于某OA系统,中秋节安排了统一假期,但某些部门中秋节必须轮班,但可以节后进行调休申请。另外针对个别人员,比如电工、安防等个别对象需要派一到两个人留守,在节前申报了坚守岗位的名单后,office boy在OA系统上通过拖拽的方式,统一调整的内部员工的假期。
设计如下:
角色 |
实例 |
描述 |
Component |
AttendanceComponent |
考勤 |
Leaf |
EmployeeLeaf |
员工个人的考勤 |
Composite |
DepartmentComposite |
整个部门的考勤 |
组合模式(Composite Pattern)和企业级设计模式的“对象-关系”映射相对应,但这里只讨论代码层面的映射关系,设计如下
其中要求DepartmentComposite
将描述为一种树结构,下面是部分代码实现,
Component接口,
1 2 3 4 5 6 7 8 9
| public interface AttendanceComponent {
void punchIn();
void punchOut();
long getAttendance(); }
|
Leaf叶子节点,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class EmployeeLeaf implements AttendanceComponent {
private long attendance = 0L;
private OffsetDateTime punchInTime; private OffsetDateTime punchOutTime;
@Override public void punchIn() { punchInTime = OffsetDateTime.now(); }
@Override public void punchOut() { punchOutTime = OffsetDateTime.now(); }
@Override public long getAttendance() { if (attendance == 0 && (punchOutTime != null && punchInTime != null)) { attendance = Duration.between(punchInTime, punchOutTime).toMinutes(); } return attendance; } }
|
Composite组合类,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class DepartmentComposite implements AttendanceComponent {
private final Set<AttendanceComponent> components = new HashSet<>();
@Override public void punchIn() { for (AttendanceComponent component : components) { component.punchIn(); } }
@Override public void punchOut() { for (AttendanceComponent component : components) { component.punchOut(); } }
@Override public long getAttendance() { return components.stream().mapToLong(AttendanceComponent::getAttendance).sum(); }
public void add(AttendanceComponent component) { components.add(component); }
public void remove(AttendanceComponent component) { components.remove(component); } }
|
总结
组合模式(Composite Pattern) 通过继承保持了单一职责原则,通过集合操作实现了“整体-部分”的一致性操作。