# 组合模式(Composite Pattern)
代码地址
- Github:DesignPattern/src/main/java/com/design/composite (opens new window)
- Gitee(码云):DesignPattern/src/main/java/com/design/composite (opens new window)
# 1. 介绍
组合模式,又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构,其实就是类似树的应用
# 1.1. 特点
待补充
# 1.2. 结构
待补充
# 1.3. 优缺点
- 意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性
- 主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦
- 何时使用:
- 您想表示对象的部分-整体层次结构(处理树形结构数据)
- 您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
- 如何解决:树枝和叶子实现统一接口,树枝内部组合该接口
- 关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component
- 注意事项:定义时为具体类
- 优点:
- 高层模块调用简单
- 节点自由增加,符合开闭原则
- 缺点:
- 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则
- 树形处理较为复杂
- 应用场景
- 树形菜单,文件、文件夹的管理
# 2. 代码
两个示例
# 2.1. 员工示例
/**
* 创建 Employee 类,该类带有 Employee 对象的列表
*
* @author wliduo[i@dolyw.com]
* @date 2023/1/31 14:07
*/
public class Employee {
private String name;
private String dept;
private int salary;
private List<Employee> subordinates;
public Employee(String name, String dept, int sal) {
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new ArrayList<>();
}
public void add(Employee e) {
subordinates.add(e);
}
public void remove(Employee e) {
subordinates.remove(e);
}
public List<Employee> getSubordinates() {
return subordinates;
}
public String toString() {
return ("Employee :[ Name : " + name
+ ", dept : " + dept + ", salary :"
+ salary + " ]");
}
}
/**
* 组合模式
*
* 使用 Employee 类来创建和打印员工的树形层次结构
*
* @author wliduo[i@dolyw.com]
* @date 2023/1/31 14:07
*/
public class Main {
public static void main(String[] args) {
Employee Ceo = new Employee("王明", "CEO", 30000);
Employee headSales = new Employee("销售主管", "销售部门", 20000);
Employee headMarketing = new Employee("营销主管", "营销部门", 20000);
Employee clerk1 = new Employee("文员1", "营销部门", 10000);
Employee clerk2 = new Employee("文员2", "营销部门", 10000);
Employee sales1 = new Employee("销售1", "销售部门", 10000);
Employee sales2 = new Employee("销售2", "销售部门", 10000);
Ceo.add(headSales);
Ceo.add(headMarketing);
headSales.add(sales1);
headSales.add(sales2);
headMarketing.add(clerk1);
headMarketing.add(clerk2);
// 打印该组织的所有员工
System.out.println(Ceo);
for (Employee headEmployee : Ceo.getSubordinates()) {
System.out.println(headEmployee);
for (Employee employee : headEmployee.getSubordinates()) {
System.out.println(employee);
}
}
}
}
Employee :[ Name : 王明, dept : CEO, salary :30000 ]
Employee :[ Name : 销售主管, dept : 销售部门, salary :20000 ]
Employee :[ Name : 销售1, dept : 销售部门, salary :10000 ]
Employee :[ Name : 销售2, dept : 销售部门, salary :10000 ]
Employee :[ Name : 营销主管, dept : 营销部门, salary :20000 ]
Employee :[ Name : 文员1, dept : 营销部门, salary :10000 ]
Employee :[ Name : 文员2, dept : 营销部门, salary :10000 ]
# 2.2. 节点示例
/**
* 节点
*
* @author wliduo[i@dolyw.com]
* @date 2023/1/31 14:15
*/
abstract public class Node {
abstract public void p();
}
/**
* 叶子节点
*
* @author wliduo[i@dolyw.com]
* @date 2023/1/31 14:15
*/
public class LeafNode extends Node {
String content;
public LeafNode(String content) {
this.content = content;
}
@Override
public void p() {
System.out.println(content);
}
}
/**
* 分支节点
*
* @author wliduo[i@dolyw.com]
* @date 2023/1/31 14:15
*/
class BranchNode extends Node {
List<Node> nodes = new ArrayList<>();
String name;
public BranchNode(String name) {
this.name = name;
}
@Override
public void p() {
System.out.println(name);
}
public void add(Node n) {
nodes.add(n);
}
}
/**
* 组合模式
*
* 模拟树形层次结构输出
*
* @author wliduo[i@dolyw.com]
* @date 2023/1/31 14:07
*/
public class Main {
public static void main(String[] args) {
BranchNode root = new BranchNode("章节");
BranchNode chapter1 = new BranchNode("章节1");
BranchNode chapter2 = new BranchNode("章节2");
Node r1 = new LeafNode("尾声");
Node c11 = new LeafNode("小结1-1");
Node c12 = new LeafNode("小结1-2");
BranchNode b21 = new BranchNode("选读1");
Node c211 = new LeafNode("选读1小结1");
Node c212 = new LeafNode("选读1小结2");
root.add(chapter1);
root.add(chapter2);
root.add(r1);
chapter1.add(c11);
chapter1.add(c12);
chapter2.add(b21);
b21.add(c211);
b21.add(c212);
tree(root, 0);
}
public static void tree(Node b, int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("--");
}
b.p();
if (b instanceof BranchNode) {
for (Node n : ((BranchNode) b).nodes) {
tree(n, depth + 1);
}
}
}
}
章节
--章节1
----小结1-1
----小结1-2
--章节2
----选读1
------选读1小结1
------选读1小结2
--尾声