• 组合模式(Composite Pattern)


    组合模式,又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

    树形结构是很常见的,比如目录系统,随便点开一个文件夹,文件夹下面可能有文件,也有子文件夹,子文件夹中还有子子文件夹和文件等。还有公司的部门构造等,展开来看都是树形的结构。

    将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

    优点: 1、高层模块调用简单。 2、节点自由增加。

    缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

    使用场景:1、你想表示对象的部分-整体层次结构(树形结构)。 2、希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。部分、整体场景,如树形菜单,文件、文件夹的管理。

    模式的结构:在组合模式结构图中包含如下几个角色

    • Component(抽象构件):它可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,如增加子构件、删除子构件、获取子构件等。

    • Leaf(叶子构件):它在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。

    • Composite(容器构件):它在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。

    示例:

    我们有一个类 Employee,该类被当作组合模型类。CompositePatternDemo 类使用 Employee 类来添加部门层次结构,并打印所有员工。

    先创建 Employee 类,该类带有 Employee 对象的列表。

    Employee.java

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. public class Employee {
    4. private String name;
    5. private String dept;
    6. private int salary;
    7. private List subordinates; //构造函数
    8. public Employee(String name, String dept, int sal) {
    9. this.name = name;
    10. this.dept = dept;
    11. this.salary = sal;
    12. subordinates = new ArrayList();
    13. }
    14. public void add(Employee e) {
    15. subordinates.add(e);
    16. }
    17. public void remove(Employee e) {
    18. subordinates.remove(e);
    19. }
    20. public List getSubordinates() {
    21. return subordinates;
    22. }
    23. public String toString() {
    24. return ("Employee :[ Name : " + name + ", dept : " + dept + ", salary :" + salary + " ]");
    25. }
    26. }

    使用 Employee 类来创建和打印员工的层次结构。

    CompositePatternDemo.java

    1. public class CompositePatternDemo {
    2. public static void main(String[] args) {
    3. Employee CEO = new Employee("John", "CEO", 30000);
    4. Employee headSales = new Employee("Robert", "Head Sales", 20000);
    5. Employee headMarketing = new Employee("Michel", "Head Marketing", 20000);
    6. Employee clerk1 = new Employee("Laura", "Marketing", 10000);
    7. Employee clerk2 = new Employee("Bob", "Marketing", 10000);
    8. Employee salesExecutive1 = new Employee("Richard", "Sales", 10000);
    9. Employee salesExecutive2 = new Employee("Rob", "Sales", 10000);
    10. CEO.add(headSales);
    11. CEO.add(headMarketing);
    12. headSales.add(salesExecutive1);
    13. headSales.add(salesExecutive2);
    14. headMarketing.add(clerk1);
    15. headMarketing.add(clerk2);
    16. //打印该组织的所有员工
    17. // System.out.println(CEO);
    18. for (Employee headEmployee : CEO.getSubordinates()) {
    19. System.out.println(headEmployee);
    20. for (Employee employee : headEmployee.getSubordinates()) {
    21. System.out.println(employee);
    22. }
    23. }
    24. }
    25. }

    执行程序,输出结果为:

    Employee :[ Name : John, dept : CEO, salary :30000 ] Employee :[ Name : Robert, dept : Head Sales, salary :20000 ] Employee :[ Name : Richard, dept : Sales, salary :10000 ] Employee :[ Name : Rob, dept : Sales, salary :10000 ] Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ] Employee :[ Name : Laura, dept : Marketing, salary :10000 ] Employee :[ Name : Bob, dept : Marketing, salary :10000 ]
    
  • 相关阅读:
    开发区块链DApp应用,引领数字经济新潮流
    浅谈 UUID 生成原理及优缺点
    为什么Java有GC调优而没听说过有CLR的GC调优?
    web前端期末大作业——基于Bootstrap响应式汽车经销商4S店官网21页
    C++之lambda匿名函数总结(二百四十五)
    C#复杂XML反序列化为实体对象两种方式
    Mysql
    羽夏 Bash 简明教程(下)
    快速非支配排序 python版
    mindspore详解
  • 原文地址:https://blog.csdn.net/u013773608/article/details/126052099