❤ 作者主页:欢迎来到我的技术博客😎
❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~*
🍊 如果文章对您有帮助,记得关注、点赞、收藏、评论⭐️⭐️⭐️
📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉
文章目录
- 一、组合模式的定义
- 二、组合模式的结构
- 三、组合模式的实现
- 四、组合模式的分类
- 五、组合模式的优缺点
- 六、组合模式的使用场景
一、组合模式的定义
组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成 树状结构 以表示 “部分-整体”的层次结构。通过组合模式,客户端可以统一对待单个对象和组合对象,使得用户在使用单个对象和组合对象时无需区分它们的差异。
二、组合模式的结构
组合模式包含以下的重要角色:
- 抽象根节点(Component): 定义了抽象类或接口,声明了组件对象的通用接口,包括对叶子节点和容器节点的操作。
- 容器节点(Composite): 实现了Component接口的容器节点对象,它包含叶子节点和/或其他容器节点,具有对子节点进行管理的能力。
- 叶子节点(Leaf): 实现了Component接口的叶子节点对象,它是组合中的最小单位,不能包含其他子节点。
三、组合模式的实现
需求案例:在公司的组织架构管理系统中,可以包含公司、部门、员工级别,现在需要展示出公司的层级结构,因此使用组合模式来描述公司的层级结构,我们的需求是打印出公司所包含的部门以及员工。
树形结构如下:
使用组合模式实现上述案例,类图如下:
具体的类设计如下:
组件接口:
public abstract class OrganizationComponent {private String name;private String description;public OrganizationComponent(String name, String description) {this.name = name;this.description = description;}public String getName() {return name;}public String getDescription() {return description;}// 叶子节点不需要实现,故不定义成抽象方法,而是采用默认实现protected void add(OrganizationComponent organizationComponent) {// 默认实现throw new UnsupportedOperationException();}protected void remove(OrganizationComponent organizationComponent) {// 默认实现throw new UnsupportedOperationException();}// 抽象方法print(),子类都需要实现protected abstract void print();
}
容器节点(公司):
public class Company extends OrganizationComponent {private List<OrganizationComponent> subComponents = new ArrayList<>();public Company(String name, String description) {super(name, description);}public void addComponent(OrganizationComponent component) {subComponents.add(component);}public void removeComponent(OrganizationComponent component) {subComponents.remove(component);}@Overrideprotected void print() {System.out.println(getName() + "(" + getDescription() + ")");for (OrganizationComponent component : subComponents) {component.print();}}
}
容器节点(部门):
public class Department extends OrganizationComponent {private List<OrganizationComponent> subComponents = new ArrayList<>();public Department(String name, String description) {super(name, description);}public void addComponent(OrganizationComponent component) {subComponents.add(component);}public void removeComponent(OrganizationComponent component) {subComponents.remove(component);}@Overrideprotected void print() {System.out.println("- " + getName() + "(" + getDescription() + ")");for (OrganizationComponent component : subComponents) {component.print();}}
}
叶子节点(员工):
public class Employee extends OrganizationComponent {public Employee(String name, String description) {super(name, description);}@Overrideprotected void print() {System.out.println("-- " + getName() + "(" + getDescription() + ")");}
}
客户端类:
public class client {public static void main(String[] args) {Employee emp1 = new Employee("张三", "软件工程师");Employee emp2 = new Employee("李四", "UI设计师");Department engineering = new Department("工程部", "开发部门");engineering.addComponent(emp1);engineering.addComponent(emp2);Employee emp3 = new Employee("王五", "市场专员");Employee emp4 = new Employee("赵六", "销售代表");Department marketing = new Department("市场部", "市场部门");marketing.addComponent(emp3);marketing.addComponent(emp4);Company myCompany = new Company("xxx公司", "科技发展有限公司");myCompany.addComponent(engineering);myCompany.addComponent(marketing);// 显示公司组织结构myCompany.print();}}
测试结果如下:
四、组合模式的分类
在使用组合模式时,根据组件的角色和结构的复杂性,我们可将组合模式分为透明组合模式和安全组合模式两种形式。
-
透明组合模式(Transparent Composite Pattern):
在透明组合模式中,抽象组件(Component)类中声明了所有用于管理子对象的方法,包括添加、移除和获取子对象等。具体叶子节点和容器节点都继承自抽象组件,并实现这些方法。这样客户端对于叶子节点和容器节点无需区分,可以统一使用。 -
安全组合模式(Safe Composite Pattern):
在安全组合模式中,抽象组件(Component)类中不声明用于管理子对象的方法,而是在具体叶子节点和容器节点中进行实现。这样客户端需要区分叶子节点和容器节点,使用时需要注意调用正确的方法。
选择透明组合模式还是安全组合模式取决于应用的需求和设计的考虑。透明组合模式提供了更统一的接口,但可能暴露一些对于叶子节点不适用的方法,而安全组合模式更加安全,但客户端需要更多的责任来判断调用的正确方法。
五、组合模式的优缺点
优点:
- 统一接口: 组合模式通过使用统一的接口,使得客户端可以一致地处理单个对象和组合对象,简化了客户端的代码。
- 灵活性: 可以通过组合模式构建复杂的 树形结构,使得系统具有更高的灵活性和可扩展性。可以随时添加新的叶子节点或容器节点,而不需要修改已有的代码。
- 可重用性: 叶子节点和容器节点的组合关系使得这些节点可以被重复使用,促进了代码的重用。
- 简化客户端代码: 客户端无需关心处理单个对象还是组合对象,可以简化客户端代码,提高代码的可维护性。
缺点:
- 可能过于一般化: 在某些情况下,组合模式可能过于一般化,不容易满足特定的需求。例如,可能会导致在叶子节点和容器节点上都定义了一些对于某个节点类型不适用的操作。
- 可能导致性能问题: 在处理大型树形结构时,组合模式可能导致性能问题,因为递归地处理整个结构可能会引起性能开销。
- 难以限制组件类型: 组合模式难以限制组件类型,因为客户端对于叶子节点和容器节点的操作是一致的。这可能导致在不同类型的组件上执行不适用的操作。
六、组合模式的使用场景
- 树形结构: 当系统中的对象具有部分-整体的层次结构,并且可以表示为树形结构时,适合使用组合模式。例如,组织架构、文件系统等都可以使用组合模式来表示。
- 管理和操作集合对象: 当需要对集合对象以统一的方式进行管理和操作时,可以考虑使用组合模式。这样可以统一处理单个对象和组合对象,无需区分它们的差异。
- 用户界面元素: 在构建用户界面时,可能存在层级嵌套的元素,如面板、按钮、复选框等。使用组合模式可以方便地管理和操作这些用户界面元素。
- 文件和文件夹管理: 文件系统中的文件和文件夹也是典型的组合结构。组合模式可以用于处理文件和文件夹之间的关系,统一操作这些对象。
- 组件化设计: 在软件设计中,当需要构建可重用的组件并且这些组件之间存在层次关系时,可以考虑使用组合模式。这有助于提高组件的灵活性和可扩展性。
- 部门-整体关系的场景: 任何具有部分-整体关系的场景都可能适合使用组合模式。例如,汽车的部件组装、家具的装配等都可以考虑使用组合模式。
非常感谢您阅读到这里,如果这篇文章对您有帮助,希望能留下您的点赞👍 关注💖 分享👥 留言💬thanks!!!