Combination mode of "Design Pattern"

1. Preface _

We must be very familiar with the above two pictures. Both pictures can be regarded as a file structure. We call this structure a tree structure . In the data structure, we know that we can traverse the entire tree by calling a certain method. When we find a leaf node, we can perform related operations on the leaf node. We can understand this tree as a large container, which contains many member objects. These member objects can be either container objects or leaf objects. However, due to the functional differences between container objects and leaf objects, we must distinguish between container objects and leaf objects during use. However, this will bring unnecessary trouble to customers. As a customer, it always hopes to be able to Treat container objects and leaf objects consistently. This is the design motivation of the combination pattern. 

2. What is the combination mode?

The combination mode recursively combines leaf objects and container objects to form a tree structure to represent the "part-whole" hierarchy, allowing users to use single objects and combined objects consistently, and can handle combinations like leaf objects. Objects without distinction, allowing user programs to be decoupled from the internal structure of complex elements.

The most critical thing about the combination pattern is that leaf objects and combination objects implement the same abstract construction class. It can represent both leaf objects and container objects. Customers only need to program for this abstract construction class. This is how the combination pattern can The reason why leaf nodes and object nodes are processed consistently.

Through the combination mode, the hierarchical structure of complex objects can be clearly defined. Leaf objects can be combined into more complex container objects, and container objects can be combined, so that continuous recursion forms a complex tree structure; at the same time, in the combination mode It is also easier to add new object constructs, and the client does not have to change the original code because of the addition of new object components.

The picture at the top of the article shows the computer file system. The file system is composed of files and directories. The directory can also contain files or directories. The computer file system is organized using a recursive structure, which is very suitable for such data structures. Use combination mode.

3. UML structure diagram

The combination mode mainly includes the following roles:

  • Component: abstractly constructs classes, objects in the composition declare interfaces, and, where appropriate, implement the default behavior of the interfaces common to all classes. Declare an interface for accessing and managing Component subcomponents. 
  • Leaf: leaf object. Leaf nodes have no child nodes. 
  • Composite: Container object, which defines the behavior of branch nodes and is used to store sub-components and implement operations related to sub-components in the Component interface, such as adding (add) and deleting (remove).

From the pattern structure, we can see that both leaf nodes and container objects implement the Component interface, which is also the key to treating leaf objects and container objects consistently. 

3. Code implementation

3.1. Code implementation 1

In the file system, there may be files in many formats, such as pictures, text files, video files, etc. The browsing methods of these different format files are different. At the same time, browsing the folder is browsing the files in the folder. But for customers, they are all browsing files, and there is no difference between the two. Now only the combination mode is used to simulate browsing files. UML structure diagram:

The first is the file class: File.java

public abstract class File {
    String name;
    
    public File(String name){
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public abstract void display();
}

Then there is the folder class: Folder.java, which contains three methods for adding, deleting and browsing files.

public class Folder extends File{
    private List<File> files;
    
    public Folder(String name){
        super(name);
        files = new ArrayList<File>();
    }
    
    /**
     * 浏览文件夹中的文件
     */
    public void display() {
        for(File file : files){
            file.display();
        }
    }
    
    /**
     * @desc 向文件夹中添加文件
     * @param file
     * @return void
     */
    public void add(File file){
        files.add(file);
    }
    
    /**
     * @desc 从文件夹中删除文件
     * @param file
     * @return void
     */
    public void remove(File file){
        files.remove(file);
    }
}

Then there are three file classes: TextFile.java, ImageFile.java, VideoFile.java

public class TextFile extends File{
 
    public TextFile(String name) {
        super(name);
    }
 
    public void display() {
        System.out.println("这是文本文件,文件名:" + super.getName());
    }
}
 
public class ImagerFile extends File{
 
    public ImagerFile(String name) {
        super(name);
    }
 
    public void display() {
        System.out.println("这是图像文件,文件名:" + super.getName());
    }
}
 
public class VideoFile extends File{
 
    public VideoFile(String name) {
        super(name);
    }
 
    public void display() {
        System.out.println("这是影像文件,文件名:" + super.getName());
    }
}

Finally the client:

public class Client {
    public static void main(String[] args) {
        /**
         * 我们先建立一个这样的文件系统
         *                  总文件
         *                  
         *   a.txt    b.jpg                   c文件夹              
         *                      c_1.text  c_1.rmvb    c_1.jpg                                                      
         */ 
        //总文件夹
        Folder zwjj = new Folder("总文件夹");
        //向总文件夹中放入三个文件:1.txt、2.jpg、1文件夹
        TextFile aText= new TextFile("a.txt");
        ImagerFile bImager = new ImagerFile("b.jpg");
        Folder cFolder = new Folder("C文件夹");
        
        zwjj.add(aText);
        zwjj.add(bImager);
        zwjj.add(cFolder);
        
        //向C文件夹中添加文件:c_1.txt、c_1.rmvb、c_1.jpg 
        TextFile cText = new TextFile("c_1.txt");
        ImagerFile cImage = new ImagerFile("c_1.jpg");
        VideoFile cVideo = new VideoFile("c_1.rmvb");
        
        cFolder.add(cText);
        cFolder.add(cImage);
        cFolder.add(cVideo);
        
        //遍历C文件夹
        cFolder.display();
        //将c_1.txt删除
        cFolder.remove(cText);
        System.out.println("-----------------------");
        cFolder.display();
    }
}

operation result:

3.2. Code implementation 2

Code example:  

package com.mashibing.dp.composite;

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

abstract class Node {
    abstract public void p();
}

class LeafNode extends Node {
    String content;
    public LeafNode(String content) {this.content = content;}

    @Override
    public void p() {
        System.out.println(content);
    }
}

class BranchNode extends Node {
    List<Node> nodes = new ArrayList<>();

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

    @Override
    public void p() {
        System.out.println(name);
    }

    public void add(Node n) {
        nodes.add(n);
    }
}


public class Main {
    public static void main(String[] args) {

        BranchNode root = new BranchNode("root");
        BranchNode chapter1 = new BranchNode("chapter1");
        BranchNode chapter2 = new BranchNode("chapter2");
        Node r1 = new LeafNode("r1");
        Node c11 = new LeafNode("c11");
        Node c12 = new LeafNode("c12");
        BranchNode b21 = new BranchNode("section21");
        Node c211 = new LeafNode("c211");
        Node c212 = new LeafNode("c212");

        root.add(chapter1);
        root.add(chapter2);
        root.add(r1);
        chapter1.add(c11);
        chapter1.add(c12);
        chapter2.add(b21);
        b21.add(c211);
        b21.add(c212);

        tree(root, 0);

    }

    static void tree(Node b, int depth) {
        for(int i=0; i<depth; i++) System.out.print("--");
        b.p();

        if(b instanceof BranchNode) {
            for (Node n : ((BranchNode)b).nodes) {
                tree(n, depth + 1);
            }
        }
    }
}

operation result:

Reference article:  Structural type of Java design pattern: combination pattern_Zhang Weipeng's blog-CSDN blog

Guess you like

Origin blog.csdn.net/m0_50370837/article/details/126304581