Design mode [11] - combination mode

Posted by dlf on Fri, 21 Jan 2022 15:53:21 +0100

The beginning is still like that. Please look down

What is the combination mode?

Combination mode, which combines objects into a tree structure to represent the "part whole" hierarchy. (Baidu Encyclopedia)

In fact, the combination pattern, also known as the partial whole pattern, is used to treat a group of similar objects as a single object. The combination mode combines objects according to the tree structure, which is used to represent the partial and overall levels. This type of design pattern is a structural pattern, which creates a tree structure of object groups.

Keywords: consistency, whole, part

For example, the organizational structure of the company is a tree structure:

There are departments and people under the company. People belong to departments, and departments can have sub departments. If we abstract the above nodes, whether organizations or people, into a node, we don't need to care whether the current node is people or departments. When calculating the number of people or traversing, we treat them equally.

In addition, in Java Swing programming, the term Container is generally used: Container. We can put sub containers or specific components in the Container, such as Button or Checkbox. In fact, this is also a part whole thinking.

In addition, the most classic is the representation of folders and files. A folder (container object) can store both folders (container object) and files (leaf object). If you spread out each node of the tree, it is List. The tree structure can more intuitively reflect the relationship between each node and the whole.

Why do you need this model? What is its purpose?

The main purpose is to provide consistent usage. Even if the attribute difference between the container object and the leaf object may be very large, we want to abstract the same place and deal with it consistently.

Role of composite mode

There are generally three roles in the combination mode:

  • Abstract Component: it is generally an interface or abstract class. It is the object declaration interface of leaf Component and container Component to abstract the methods of accessing and managing child components.
  • Leaf node: represents a leaf node object in a combination. A leaf node has no child nodes and no child components.
  • Container component: a container node can contain child nodes, which can be leaf nodes or container nodes.

Note: the key point is the abstract component. All nodes are unified. The caller is no longer required to care about the difference between leaf nodes and non leaf nodes.

Two implementations of combination mode

There are two different implementations of composite mode, namely transparent mode and security mode:

The difference between the two is that the transparent mode puts the combined methods into the abstract class, while the security mode puts them into the concrete implementation class

Transparent mode

Transparent mode abstracts the combined methods into abstract classes. Both leaf nodes and composite nodes have the same methods, which is consistent in external processing. However, in fact, some methods are useless and cumbersome for leaf nodes.

The following is the code implementation:

Abstract class, which requires the implementation of three methods: add, delete and display:

package designpattern.composite;

public abstract class Component {
    String name;

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

    public abstract void add(Component component);

    public abstract void remove(Component component);

    public abstract void show(int depth);
}

Composite class:

import java.util.ArrayList;
import java.util.List;

public class Composite extends Component {
    List<Component> childs = new ArrayList<>();

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

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

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

    @Override
    public void show(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("    ");
        }
        System.out.println(name + ": ");
        for (Component component : childs) {
            component.show(depth + 1);
        }
    }
}

Leaves:

public class Leaf extends Component {
    public Leaf(String name) {
        super(name);
    }

    @Override
    public void add(Component component) {

    }

    @Override
    public void remove(Component component) {

    }

    @Override
    public void show(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("    ");
        }
        System.out.println(name);
    }
}

Test class:

public class Test {
    public static void main(String[] args) {
        Composite folderRoot = new Composite("Memo folder");
        folderRoot.add(new Leaf("word file"));
        folderRoot.add(new Leaf("ppt file"));

        Composite folderLevel1 = new Composite("Weekly report folder");
        folderLevel1.add(new Leaf("20210101 weekly"));
        folderRoot.add(folderLevel1);


        Composite folderLevel2 = new Composite("Notes folder");
        folderLevel2.add(new Leaf("jvm.ppt"));
        folderLevel2.add(new Leaf("redis.txt"));
        folderLevel1.add(folderLevel2);


        folderRoot.add(new Leaf("demand.txt"));


        Leaf leaf = new Leaf("bug single.txt");
        folderRoot.add(leaf);
        folderRoot.remove(leaf);

        folderRoot.show(0);
    }
}

The operation results are as follows:

Memo folder: 
    word file
    ppt file
    Weekly report folder: 
        20210101 weekly
        Notes folder: 
            jvm.ppt
            redis.txt
    demand.txt

You can see that the above is the result of a tree. Whether it is a leaf node or a combination node, the operation is the same.

safe mode

Security mode is to separate the characteristics of leaf nodes and composite nodes. Only composite nodes can have add and delete operations, and both will have display operations. However, if leaf nodes and composite nodes are exposed at the same time, special judgment needs to be made when using them.

Abstract components:

public abstract class Component {
    String name;

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

    public abstract void show(int depth);
}

Component components:

public class Composite extends Component {
    List<Component> childs = new ArrayList<>();

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

    public void add(Component component) {
        this.childs.add(component);
    }

    public void remove(Component component) {
        this.childs.remove(component);
    }

    @Override
    public void show(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("    ");
        }
        System.out.println(name + ": ");
        for (Component component : childs) {
            component.show(depth + 1);
        }
    }
}

Leaf node:

public class Leaf extends Component {
    public Leaf(String name) {
        super(name);
    }

    @Override
    public void show(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("    ");
        }
        System.out.println(name);
    }
}

The test class remains unchanged, and the test results are the same:

Memo folder: 
    word file
    ppt file
    Weekly report folder: 
        20210101 weekly
        Notes folder: 
            jvm.ppt
            redis.txt
    demand.txt

In the security mode, the leaf node has no redundant methods and no empty methods. When it is called outside, it will not call the empty methods. However, you need to judge the node to know which method can be adjusted and which method cannot be adjusted.

To summarize

Advantages of combined mode:

  • Complex objects can be defined hierarchically to represent part and all. The client can ignore the differences of different nodes.
  • From the high-level call, you can call each part smoothly, with strong consistency.
  • The nodes are freely matched and have high flexibility.

Disadvantages:

  • When using the composite pattern, the declarations of its leaves and composite nodes are implementation classes, not interfaces, which violates the dependency inversion principle.

Usage scenario:

  • You want to ignore the differences of each part and use it consistently by the client
  • It needs to be represented as a tree structure to represent the structural hierarchy of "whole part".

End with a netizen's sentence:

"When Zhang Wuji learned Taijiquan, he forgot all the moves and knocked down the" two old men in the dark "and the so-called" no moves in the heart ". The design mode can be described as a move. If he learned all kinds of modes first, forgot all the modes and did what he wanted, it can be described as the highest state of OO."

[about the author]:
Qin Huai, the official account of Qin Huai grocery store, author's personal website: http://aphysia.cn , the road of technology is not for a while, with high mountains and long rivers. Even if it is slow, it will not stop.

Sword finger Offer all questions PDF

Open source programming notes

Design pattern series:

Topics: Java Design Pattern