Introduction
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 base contract with composite class to allow the creation of nested objects.
- Composite: This the player that will implement the contract defined by the component.
- Client: With the help of composite player, this player will complete the system hierarchy for 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 Abstract block with Add, Remove block features. If we want we can implement Add, 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.
- using System.Collections.Generic;
-
- namespace Composite.Design.Pattern.Demo.Contract
- {
- public abstract class AbstractBlock
- {
- public string Name { get; set; }
- public double Size { get; set; }
- public abstract void BuildBlock();
- public List<AbstractBlock> SubBlocks { get; set;}
- }
- }
Now implement Composite object; i.e., Block by implementing/inheriting component i.e. in our code AbstractBlock
- using Composite.Design.Pattern.Demo.Contract;
- using System.Collections.Generic;
- using static System.Console;
-
- namespace Composite.Design.Pattern.Demo.Business
- {
- public class Block : AbstractBlock
- {
- public Block()
- {
- SubBlocks = new List<AbstractBlock>();
- }
- public override void BuildBlock() => WriteLine($"Block built with Name {Name} with size {Size} unit");
- }
- }
In the above code we can see that, we provided the implementation for BuildBlock method. Based on our need we can make concrete or non-concreate method as well.
Below is the client class code:
- using Composite.Design.Pattern.Demo.Contract;
- using static System.Console;
- using Composite.Design.Pattern.Demo.Business;
- using Newtonsoft.Json;
-
- namespace Composite.Design.Pattern.Demo
- {
- class Client
- {
- static void Main(string[] args)
- {
- AbstractBlock smartCity = new Block
- {
- Name = "SmartCity",
- Size = 100000
- };
-
- AbstractBlock smartlayOut = new Block()
- {
- Name = "SmartlayOut",
- Size = 10000,
- };
- smartCity.SubBlocks.Add(smartlayOut);
-
- AbstractBlock smartHome = new Block()
- {
- Name = "smartHome",
- Size = 1000,
- };
- smartlayOut.SubBlocks.Add(smartHome);
-
- AbstractBlock smartRoom = new Block()
- {
- Name = "smartRoom",
- Size = 1000,
- };
- smartHome.SubBlocks.Add(smartRoom);
-
- AbstractBlock smartLocker = new Block()
- {
- Name = "smartLocker",
- Size = 20,
- };
- smartRoom.SubBlocks.Add(smartLocker);
-
- AbstractBlock smartFolder = new Block()
- {
- Name = "smartFolder",
- Size = 10,
- };
- smartRoom.SubBlocks.Add(smartFolder);
-
- AbstractBlock smartFile = new Block()
- {
- Name = "smartFile",
- Size = 5,
- };
- smartFolder.SubBlocks.Add(smartFile);
-
- Build(smartCity);
- WriteLine();
- string json = JsonConvert.SerializeObject(smartCity, Formatting.Indented);
- WriteLine(json);
-
- ReadLine();
- }
-
- private static void Build(AbstractBlock block)
- {
- block.BuildBlock();
- block?.SubBlocks?.ForEach(b => Build(b));
- }
- }
- }
In above code we can see that the client has utilized composite object and 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 see the same hierarchy in json format. For easy understating I Serialized object into Json. Below is the output:
When we have a requirement of implementing 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 number of blocks inside blocks.
Summary
Above is the simple example of using composite design pattern, you can download the uploaded source code and try adding more blocks. I hope it helps.