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
- Component: this player defines a base contract with the composite class to allow to create nested objects.
- Composite: this player, is one who will implement the contract defined by the component.
- Client: this player, with the help of a composite player, will complete the system hierarchy for a particular requirement
We will see with an example.
Requirement
Build a smart city with smart block features.
We will define 3 players.
- AbstractBlock: Component
- Block: Composite
- Client
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.
- Smart City followed by Smart Layout
- Smart Layout followed by Smart Home
- Smart Home followed by Smart Room
- Smart Room followed by Smart Locker
- Smart Locker followed by Smart Folder
- Smart Folder followed by Smart File
After executing this code we can same hierarchy in tree format. For easy understating, I put snap ob object hierarchy in tree format.
Below is the output snap.
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.