Introduction

A composite design pattern is a structural design pattern. It allows developers to create multiple nested objects of the same type to complete one single system hierarchy.

Players in this pattern

We will see with an example.

Requirement

Build a smart city with smart block features.

We will define 3 players.

We will build an Abstract block with Add and remove block features. If we want we can implement Add, and Remove features explicitly. In my case, I am using List, by default I will be having Add and Remove features available for adding/removing blocks.

import java.util.List;
public abstract class AbstractBlock {
    public String name;
    public double size;
    public abstract void buildBlock();
    public List<AbstractBlock> subBlocks;
}

Now implement a Composite object i.e. Block by implementing/inheriting a component (i.e. in our code AbstractBlock).

import java.util.*;
public class Block extends AbstractBlock {
    public Block() {
        subBlocks = new ArrayList<>();
    }
    @Override
    public void buildBlock() {
        System.out.println("Block built with name " + name + " with size " + size + " unit");
    }
}

In the above code we can see that, we provided the implementation for the buildBlock method. Based on our need we can make concrete or non-concrete methods as well.

Below is the client class code.

public class Client {

    public static void main(String[] args) {
        AbstractBlock smartCity = new Block();
        smartCity.name = "SmartCity";
        smartCity.size = 100000;
        AbstractBlock smartlayOut = new Block();
        smartlayOut.name = "SmartlayOut";
        smartlayOut.size = 10000;
        smartCity.subBlocks.add(smartlayOut);
        AbstractBlock smartHome = new Block();
        smartHome.name = "smartHome";
        smartHome.size = 1000;
        smartlayOut.subBlocks.add(smartHome);
        AbstractBlock smartRoom = new Block();
        smartRoom.name = "smartRoom";
        smartRoom.size = 1000;
        smartHome.subBlocks.add(smartRoom);
        AbstractBlock smartLocker = new Block();
        smartLocker.name = "smartLocker";
        smartLocker.size = 20;
        smartRoom.subBlocks.add(smartLocker);
        AbstractBlock smartFolder = new Block();
        smartFolder.name = "smartFolder";
        smartFolder.size = 10;
        smartLocker.subBlocks.add(smartFolder);
        AbstractBlock smartFile = new Block();
        smartFile.name = "smartFile";
        smartFile.size = 5;
        smartFolder.subBlocks.add(smartFile);
        Build(smartCity);
        System.out.println();
    }
    private static void Build(AbstractBlock block) {
        block.buildBlock();
        block.subBlocks.forEach(a -> Build(a));
    }
}

In the above code, we can see that the client has a unitized composite object and is built first.

After executing this code we can same hierarchy in tree format. For easy understating, I put snap ob object hierarchy in tree format.

Hierarchy

Below is the output snap.

Below

When we have a requirement to implement some nested objects with the same type, then we can go for this design pattern.

We can extend this composite object to any extent with N numbers of blocks inside blocks.

Summary

Above is a simple example of using a composite design pattern, you can download the uploaded source code and try adding more blocks. I hope it helps.