Composite Design pattern in Java – Java中的复合设计模式

最后修改: 2018年 5月 11日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this quick tutorial, we’ll introduce the composite design pattern in Java.

在这个快速教程中,我们将介绍Java中的复合设计模式。

We’re going to describe the structure and the purpose of its use.

我们将描述其结构和使用的目的。

2. The Structure

2.结构

The composite pattern is meant to allow treating individual objects and compositions of objects, or “composites” in the same way. 

复合模式的目的是允许以同样的方式处理单个对象和对象的组合,或 “组合”。

It can be viewed as a tree structure made up of types that inherit a base type, and it can represent a single part or a whole hierarchy of objects.

它可以被看作是一个由继承基础类型的类型组成的树状结构,它可以代表单个部分或整个对象的层次结构。

We can break the pattern down into:

我们可以把这个模式分解成。

  • component – is the base interface for all the objects in the composition. It should be either an interface or an abstract class with the common methods to manage the child composites.
  • leaf – implements the default behavior of the base component. It doesn’t contain a reference to the other objects.
  • composite – has leaf elements. It implements the base component methods and defines the child-related operations.
  • client – has access to the composition elements by using the base component object.

3. Practical Example

3.实际案例

Now, let’s dive into the implementation. Let’s suppose we want to build a hierarchical structure of departments in a company.

现在,让我们深入了解一下实施情况。我们假设我们想在一个公司中建立一个部门的层次结构。

3.1. The Base Component

3.1.基础组件

As a component object we’ll define a simple Department interface:

作为一个组件对象,我们将定义一个简单的Department接口。

public interface Department {
    void printDepartmentName();
}

3.2. Leafs

3.2.叶子

For the leaf components, let’s define classes for financial and sales departments:

对于叶子组件,让我们为财务和销售部门定义类。

public class FinancialDepartment implements Department {

    private Integer id;
    private String name;

    public void printDepartmentName() {
        System.out.println(getClass().getSimpleName());
    }

    // standard constructor, getters, setters
}

The second leaf class, SalesDepartment, is similar:

第二个叶子类,SalesDepartment,是类似的。

public class SalesDepartment implements Department {

    private Integer id;
    private String name;

    public void printDepartmentName() {
        System.out.println(getClass().getSimpleName());
    }

    // standard constructor, getters, setters
}

Both classes implement the printDepartmentName() method from the base component, where they print the class names for each of them.

这两个类都实现了基础组件的printDepartmentName()方法,在这里它们都打印了它们各自的类名。

Also, as they’re leaf classes, they don’t contain other Department objects.

此外,由于它们是叶子类,它们不包含其他Department对象。

Next, let’s see a composite class as well.

接下来,我们也来看看一个复合类。

3.3. The Composite Element

3.3.复合元素

As a composite class, let’s create a HeadDepartment class:

作为一个复合类,我们来创建一个HeadDepartment类。

public class HeadDepartment implements Department {
    private Integer id;
    private String name;

    private List<Department> childDepartments;

    public HeadDepartment(Integer id, String name) {
        this.id = id;
        this.name = name;
        this.childDepartments = new ArrayList<>();
    }

    public void printDepartmentName() {
        childDepartments.forEach(Department::printDepartmentName);
    }

    public void addDepartment(Department department) {
        childDepartments.add(department);
    }

    public void removeDepartment(Department department) {
        childDepartments.remove(department);
    }
}

This is a composite class as it holds a collection of Department components, as well as methods for adding and removing elements from the list.

这是一个复合类,因为它持有一个Department组件的集合,以及从列表中添加和删除元素的方法。

The composite printDepartmentName() method is implemented by iterating over the list of leaf elements and invoking the appropriate method for each one.

复合的printDepartmentName()方法是通过遍历叶子元素的列表并为每个元素调用适当的方法来实现的。

4. Testing

4.测试

For testing purposes, let’s have a look at a CompositeDemo class:

出于测试目的,让我们看一下CompositeDemo类。

public class CompositeDemo {
    public static void main(String args[]) {
        Department salesDepartment = new SalesDepartment(
          1, "Sales department");
        Department financialDepartment = new FinancialDepartment(
          2, "Financial department");

        HeadDepartment headDepartment = new HeadDepartment(
          3, "Head department");

        headDepartment.addDepartment(salesDepartment);
        headDepartment.addDepartment(financialDepartment);

        headDepartment.printDepartmentName();
    }
}

First, we create two instances for the financial and sales departments. After, we instantiate the head department and add up the previously created instances to it.

首先,我们为财务部和销售部创建两个实例。之后,我们实例化总公司,并将之前创建的实例添加到其中。

Finally, we can test the printDepartmentName() composition method. As we expect, the output contains the class names of each leaf component:

最后,我们可以测试printDepartmentName()组成方法。正如我们所期望的,输出包含每个叶子组件的类名

SalesDepartment
FinancialDepartment

5. Conclusion

5.结论

In this article, we learned about the Composite design pattern. The write-up highlights the main structure and demonstrates the usage through the practical example.

在这篇文章中,我们了解了复合设计模式。这篇文章强调了主要的结构,并通过实际的例子演示了其用法。

As usual, the complete code is available in the Github project.

像往常一样,完整的代码可以在Github项目中找到。