Structural Design Patterns #04 - Composite

Structural Design Patterns #04 - Composite

(Image created by deepai)

This post is going to cover the composite pattern. Compared to the decorator pattern from the previous post this pattern (in my opinion) is much more simple to understand.

The problem

Let's assume we are working at an automotive company that is producing car parts on a single production line. When the production of a part is done our system needs to know that the part is finished so that it can be prepared for delivery. To tackle this problem we could come up with the following structure:

Let's say the production line can also contain assemblies of different parts, like an engine or a pipe with a welded flange. Because the assembly consists of different parts (or other assemblies) we need to set the isReadyForDelivery attribute on every part of the assembly. How could we include this logic in our software?

The solution

We can include a composite class that describes our assemblies. Also, this class would implement the IProductionItem interface. Therefore we can continue to use the existing interface.

This pattern enables us to treat single parts as well as assemblies uniformly in our software. The composite class in this case would then be responsible for delegating the work to the different parts:

interface IProductionItem
{
    void SetReadyForDelivery(bool isReady);  
}
class ProductionItemComposite : IProductionItem
{
    List<IProductionItem> assembly = new();

    [...]

    public void SetReadyForDelivery(bool isReady) 
    {
        foreach (var part in assembly) 
        {
            part.SetReadyForDelivery(isReady);
        } 
    } 
}

In general, this pattern is useful for representing part-whole hierarchies in a tree-like structure. Because the composite class contains a reference to IProductionItem an assembly can contain another assembly. Because we are using a list in the composite class the assembly could contain multiple other assemblies. Therefore this pattern enables us to represent the following tree-like structure:

As mentioned before, this structure also enables the client to treat both entities (part and whole) uniformly. A client in the given example that is using the interface does not necessarily need to know if an IProductionItem is a part or an assembly (or an assembly consisting of multiple smaller assemblies).

That's it for this post, I hope you could learn something! Additionally, if you want to get informed about future posts: sUbsCr1be t0 mY n3wslet1er!1