Note: Among the two examples in this article, the example idea of corporate structure comes from “Big Talk Design Mode”, the content and code have been modified to some extent, respect and protect the author’s copyright, hereby declare.

Contents of article series (continuously updated) :

Chapter 1: Overview, Coupling, UML, Seven Principles, Detailed Analysis and summary (Based on Java)

Chapter two: Several implementations of singleton pattern And its destruction by reflection

【 Design Pattern 】 Chapter 3: A Simple factory, factory method pattern, abstract factory pattern 】

The Builder model is not that difficult

Chapter 5: What is a Prototype Pattern? Shallow fetch shallow copy and deep copy

Article 6: Look at the adapter pattern

[Design Pattern] Chapter 7: Understand the bridge pattern with me

[Design mode] Chapter 8: Drinking soy milk is decorator mode?

[Design Pattern] Chapter 9: Combination pattern to solve the problem of hierarchical structure

[Design mode] Chapter 10: Appearance mode, the joy of driving a small broken car

[Design mode] Chapter 11: Let’s take a look at the yuan model

[Design Mode] Chapter 12: explanation of agent mode in the ticket purchase scene

A quote

In daily life, we often see some hierarchical structures, such as the relationship between [university-college-specialty] in student days, as well as the relationship between [head office-branch/department], [schoolbag – book], and in software development, [folder – file] and [container – component].

But in fact, it can be found that the commonality is in the form of large scope including small scope. For example, there are different majors under each school, for example, software engineering major under the School of Computer science. We can call it the “whole-part” mode

If we follow the simplest way to think of, it may be multi-level inheritance, such as XXX University, the following school of Computer and other schools to inherit XXX University, and software engineering, computer science and technology and other majors to inherit the school of computer

In fact, this method is divided according to the size of the organization, but from the actual point of view, in addition to its size, we tend to show its composition structure, for example, there are multiple majors under the computer school, and certain maintenance services are carried out for it, such as update traversal

And that’s what we can do with the combination pattern we’re going to talk about today

Isn’t branch two just a department

The requirements of this case are as follows: a large company that has distribution offices all over the country wants to use the same office management system in its branches all over the country, such as its headquarters in Beijing, branches in several major cities across the country, and offices in several provincial capitals. The human resources department of the parent company does not have the office management function such as finance department in all branches and offices, how to do?

(1) Analysis

First of all, let’s take a look at the relationship between the head office, branches, offices, and the departments they belong to

As can be seen from the figure, The Headquarters in Beijing is the highest level and has two most direct departments, namely, human Resources Department and Finance Department. In fact, the branch company belongs to the same level with these departments, and the two management functions, human resources Department and Finance Department, can be used in the branch company. The office level is one level down, as well.

After analyzing this diagram, we have a simple idea of how to do it. Simple parallel management is definitely not appropriate, so we make it into a tree structure, which will also be very convenient to maintain and manage

Beijing head office is just like this root node, and its subordinate branches are branches of the tree, such as the office is a smaller branch, no matter the head office or branch, or the relevant functional departments of the office (such as the finance department) have branches, so it is also a leaf node

It might be a little bit confusing to go straight to the example, but let’s set the stage by demonstrating the simplest combination pattern, and then we’ll implement the above company example

(2) Combination mode

(1) What is the combination mode

Definition: The composite pattern, sometimes called the “whole-part” pattern, is a pattern that combines objects into a tree-like hierarchy to represent the “whole-part” relationship, giving users consistent access to both individual and composite objects

(2) structure

(3) Simple code

Component declares a common interface for the branch and leaf objects in the composition

public abstract class Component {
    protected String name;

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    // Add parts
    public abstract void add(Component component);

    // Delete the component
    public abstract void remove(Component component);

    // Iterate over all child component content
    public abstract void traverseChild(a);
}
Copy the code

Leaf refers to the Leaf node, and there is no child node. All add and remove methods have no specific business, but only throw an exception, and only realize the traversal method

public class Leaf extends Component{
    @Override
    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void traverseChild(a) {
        System.out.println("Execute:" + super.getName()); }}Copy the code

Composite stands for branch. It is used to store child parts. The main function is to store and manage child parts

public class Composite extends Component {

    // To save the assembled parts
    List<Component> list = new ArrayList<Component>();

    @Override
    public void add(Component component) {
        list.add(component);
    }

    @Override
    public void remove(Component component) {
        list.remove(component);
    }

    @Override
    public void traverseChild(a) {
        System.out.println("Execute:" + name);
        for(Component c : list) { c.traverseChild(); }}}Copy the code

Test the

public class Test {
    public static void main(String[] args) {
        // Set the root node
        Composite root = new Composite();
        root.name = "Root node";

        // Add a leaf node
        Leaf leafA = new Leaf();
        leafA.setName("Leaf node A");
        Leaf leafB = new Leaf();
        leafB.setName("Leaf node B");
        // Add A and B to root
        root.add(leafA);
        root.add(leafB);
        / / traverseroot.traverseChild(); }}Copy the code

Results:

Execution: Root node Execution: leaf node A Execution: leaf node B

(4) Transparent way and safe way

In the code above, we define the add and remove methods in the abstract Component

// Add parts
public abstract void add(Component component);
// Delete the component
public abstract void remove(Component component);
Copy the code

This means that the add and remove methods need to be implemented even in the Leaf node class. (We can throw exceptions here and choose empty implementations.) This method is called transparent. It includes add and remove methods, so that all subclasses that inherit or implement this class have these methods. The advantage of such behavior is that leaf nodes and branches have completely consistent behavior interfaces, while the disadvantage is that empty implementations in leaf nodes are meaningless

Instead of declaring add and remove methods in Component, declare all methods used to manage subclass objects in Composite. This will not have the same problem. The downside is that leaves and branches no longer have the same structure, and client calls require some additional judgment

(5) the advantages and disadvantages

Advantages:

  • In a similar example, basic objects such as functional departments and composite objects such as branch offices can be combined into more complex composite objects, and composite objects can be combined
  • Client code can work with both single and composite objects consistently, regardless of whether it is working with a single object or a composite object, and the client is easy to call
  • Add new content to the assembly, do not need to modify the source code, meet the open and closed principle

Disadvantages:

  • The design is more complex, and the hierarchical relationship between classes needs to be clarified

(iii) Implementation of the company’s sample code

Let’s apply the composite pattern (transparent mode) with the above concrete example

The company’s abstract class, equivalent to the Component above

/** ** company abstract class */
public abstract class Company {
    protected String name;

    public Company(String name) {
        this.name = name;
    }

    / / add
    public abstract void add(Company company);

    / / delete
    public abstract void remove(Company company);

    / / show
    public abstract void display(int depth);

    // Perform duties
    public abstract void lineOfDuty(a);
}
Copy the code

Specific class company, equivalent to the Composite, in order to can see its hierarchical structure, the output of the console I based on the depth of the current node, increased the equal sign MyStringUtil repeatString (” = “, the depth) is encapsulates a method, Prints a string multiple times based on depth

/**
 * 具体公司类,树枝节点
 */
public class ConcreteCompany extends Company {
    // Store the kitchen branches and leaves
    private List<Company> children = new ArrayList<>();

    public ConcreteCompany(String name) {
        super(name);
    }

    @Override
    public void add(Company company) {
        children.add(company);
    }

    @Override
    public void remove(Company company) {
        children.remove(company);
    }

    @Override
    public void display(int depth) {
        // Displays the name of its branch node and traverses its children
        System.out.println(MyStringUtil.repeatString("=", depth) + name);
        for (Company c : children) {
            c.display(depth + 4); }}@Override
    public void lineOfDuty(a) {
        // Iterate over each child's node
        for(Company c : children) { c.lineOfDuty(); }}}Copy the code

This is the utility class used above

public class MyStringUtil {
    public static String repeatString(String repeatStr, int repeatNum) {
        StringBuilder stringBuilder = new StringBuilder();
        while (repeatNum-- > 0) {
            stringBuilder.append(repeatStr);
        }
        returnstringBuilder.toString(); }}Copy the code

The following are two specific departments, namely leaf nodes

/** * Hr Department */
public class HRDepartment extends Company {


    public HRDepartment(String name) {
        super(name);
    }

    @Override
    public void add(Company company) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(Company company) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void display(int depth) {

        // Displays the name of its branch node and traverses its children
        System.out.println(MyStringUtil.repeatString("=", depth) + name);
    }

    @Override
    public void lineOfDuty(a) {
        System.out.println("【" + name + ": Staff Training Management"); }}Copy the code
/** ** Finance Department */
public class FinanceDepartment extends Company {


    public FinanceDepartment(String name) {
        super(name);
    }

    @Override
    public void add(Company company) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(Company company) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void display(int depth) {


        // Displays the name of its branch node and traverses its children
        System.out.println(MyStringUtil.repeatString("=", depth) + name);
    }


    @Override
    public void lineOfDuty(a) {
        System.out.println("【" + name + ": Financial revenue and expenditure management of the company"); }}Copy the code

ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany: ConcreteCompany Such code represents its hierarchy

public class Test {
    public static void main(String[] args) {
        // Create root node
        ConcreteCompany root = new ConcreteCompany(Head Office in Beijing);
        root.add(new HRDepartment("Head Office Human Resources Department"));
        root.add(new FinanceDepartment(Head Office Finance Department));

        ConcreteCompany comp = new ConcreteCompany("Shanghai East China Branch");
        comp.add(new HRDepartment("Hr Department of East China Branch"));
        comp.add(new FinanceDepartment(Financial Department of East China Branch));

        root.add(comp);
		
        ConcreteCompany comp = new ConcreteCompany("Nanjing Office");
        comp1.add(new HRDepartment("Human Resources Department of Nanjing Office"));
        comp1.add(new FinanceDepartment("Nanjing Office Financial Department"));
        comp.add(comp1);

        System.out.println("Structure diagram :");
        root.display(1);

        System.out.println("Responsibility."); root.lineOfDuty(); }}Copy the code

Running results:

Structure: Beijing head office = = = = = = = = = = = hr head office finance department = = = = = Shanghai east China branch of = = = = = = = = = east China branch hr = = = = = = = = = east China branch of the finance department = = = = = = = = = the nanjing office = = = = = = = = = = = = = the nanjing office hr = = = = = = = = = = = = = the nanjing office finance department responsibilities: Company human resources department staff training management 】 corporate finance company, financial revenues and expenditures 】 【 east China branch of the human resources department staff training management company east China branch of the finance department 】 【 financial revenue and expenditure management nanjing office hr staff training management 】 【 nanjing office finance department 】 the company financial revenue and expenditure managementCopy the code