Design patterns: Composite

in design-patterns •  7 years ago 

workers.jpg

Hi, I’ve recently found an interesting design pattern called Composite, which is used to fold objects into a tree structure, thanks to which the client sees instead of many objects only one. And that’s the point Composite works, that client could treat many object as one. More precise about Composite further in article.

Intent

  1. Creating objects in so-called tree structures.
  2. Folding objects in such a way that the client sees many of them as one object.
  3. Recursive composition.

Problem

You can use the composite pattern when you need to operate on the hierarchy of objects. Then you will not have to refer to each of them and you will be able to treat this hierarchy as a single object.

Discussion

Referring to a group of objects as one object can be very useful in some cases, it facilitates very much the operation on the whole group, because you do not have to refer to each object in turn, you can perform the action on the whole group.

Structure

The composite, as it was said in the introduction, operates on many objects, but in sequence, below is the UML diagram of the composite pattern:

Composite.png

The diagram shows that the composite pattern consists of the following parts:

  1. Component – an abstract class or interface representing individual Leaf objects.
  2. Leaf – simple type – does not have descendants.
  3. Composite – stores simple objects (Leaf), implements the behavior of elements that it contains.

And of course from the client who operates on the data in the pattern.

Example

Composite pattern schema

But it’s best to see it in a practical example, the composite looks something like this:

interface IComponent
{
    void operation();
}
 
class Leaf : IComponent
{
    public void operation()
    {
        Console.WriteLine("display leaf "+this);
    }
}
 
class Composite : IComponent
{
    private List<IComponent> _children = new List<IComponent>();
 
    public void operation()
    {
        Console.WriteLine("display leaf " + this);
    }
 
    public void AddChild(IComponent component)
    {
        _children.Add(component);
    }
 
    public void RemoveChild(IComponent component)
    {
        _children.Remove(component);
    }
 
    public List<IComponent> GetChild()
    {
        return _children;
    }
}

As you can see in the example, the Composite class has a list to which we put objects on which we want to operate, and methods that add or remove objects from the list and I also have a method that returns us the contents of this list.

Of course, we put objects to the client’s list 🙂

static void Main(string[] args)
{
     Leaf leaf1 = new Leaf();
     Leaf leaf2 = new Leaf();
     Leaf leaf3 = new Leaf();
 
     Composite composite = new Composite();
     composite.AddChild(leaf1);
     composite.AddChild(leaf2);
     composite.AddChild(leaf3);
 
     List <IComponent> listchildren= composite.GetChild();
 
     Console.WriteLine(listchildren.Count);
 
     leaf1.operation();
     leaf2.operation();
 
     composite.operation();
 
     Console.ReadKey();
}

This is a standard scheme of composite operation, in short the composite contains a hierarchy of objects in which the main object manages its subobjects.

Result

CompositeSum.png

Real-life examples

Workplace

Let’s see now in action the composite on the example of life taken. A good example is the hierarchy in a company, there are managers who manage employees.

Let’s see how it will look like in the following example:

interface IWorker
{
    void DisplayInformationWorker();
}
 
class Worker : IWorker
{
    private string FirstName, LastName, Degree;
 
    public Worker(string firstname, string lastname, string degree)
    {
        FirstName = firstname;
        LastName = lastname;
        Degree = degree;
    }
 
    public void DisplayInformationWorker()
    {
        Console.WriteLine(FirstName + " " + LastName + " " + Degree);
    }
}
 
class Manager : IWorker
{
    private string FirstName, LastName, Degree;
    private List<IWorker> workers = new List<IWorker>();
 
    public Manager(string firstname, string lastname, string degree)
    {
        FirstName = firstname;
        LastName = lastname;
        Degree = degree;
    }
 
    public void AddWorker(IWorker worker)
    {
        workers.Add(worker);
    }
 
    public void DisplayInformationWorker()
    {
        Console.WriteLine("Subordinates manager: " + FirstName + " " + LastName);
        foreach(IWorker worker in workers)
        {
            worker.DisplayInformationWorker();
        }
    }
}

You could expect something like this, we have a manager class that can add employees, we also have a method that displays the names of employees who are subordinates of the manager, in the client it looks like this:

static void Main(string[] args)
{
    Manager manager = new Manager("Andrej","Wardalo","head of the technology department");
    manager.AddWorker(new Worker("Anna", "Karbowska","embedded systems engineer"));
    manager.AddWorker(new Worker("Mark", "Zielinski", "IOS application developer"));
    manager.AddWorker(new Worker("Slawomir", "Kowalski", "Web application developer"));
 
    manager.DisplayInformationWorker();
 
    Console.ReadKey();
}

It may also be that the manager may have other managers underneath who have other employees, in that case the call in the client would look like this:

static void Main(string[] args)
{
    Manager manager1 = new Manager("Andrej","Wardalo","head of the technology department");
    manager1.AddWorker(new Worker("Anna", "Karbowska","embedded systems engineer"));
    manager1.AddWorker(new Worker("Mark", "Zelinski", "IOS application developer"));
    manager1.AddWorker(new Worker("Slawomir", "Kowalski", "Web application developer"));
    Manager manager2 = new Manager("Jacek", "Nowak","team manager");
    manager1.AddWorker(manager2);
    manager2.AddWorker(new Worker("Waldemar", "Musal", "Evaluator"));
    manager2.AddWorker(new Worker("Jan", "Pufund", "Graphic designer"));
 
    manager1.DisplayInformationWorker();
 
    Console.ReadKey();
}

Result

compositetwo.png

Collection of figures

Let’s make an example with figures, let’s assume that we want to draw a few figures, but we do not want to deal with them individually, we only want to draw some figures and change their color on for example, red as one object. Let’s start with Component, Composite and Leaf classes.

namespace Shapes
{
    public interface IShape
    {
        void draw(string fillColor);
    }
 
    public class Triangle : IShape
    {
        public void draw(string fillColor)
        {
            Console.WriteLine("Drawing Triangle with color " + fillColor);
        }
    }
 
    public class Circle : IShape
    {
        public void draw(string fillColor)
        {
            Console.WriteLine("Drawing Circle with color " + fillColor);
        }
    }
 
    public class Drawing : IShape
    {
 
        private List<IShape> shapes = new List<IShape>();
 
        public void draw(string fillColor)
        {
            foreach (IShape sh in shapes)
            {
                sh.draw(fillColor);
            }
        }
 
        public void add(IShape s)
        {
            shapes.Add(s);
        }
 
        public void remove(IShape s)
        {
            shapes.Remove(s);
        }
 
        public void clear()
        {
            Console.WriteLine("Clearing all the shapes from drawing");
            shapes.Clear();
        }
    }
}

We see that the structure looks similar to the previous example. I do not think I need to explain anything here. Now let’s see what the customer looks like:

namespace Graphic
{
    class Program
    {
        static void Main(string[] args)
        {
            IShape tri = new Triangle();
            IShape tri1 = new Triangle();
            IShape cir = new Circle();
 
            Drawing drawing = new Drawing();
            drawing.add(tri1);
            drawing.add(tri1);
            drawing.add(cir);
 
            drawing.draw("Red");
 
            drawing.clear();
 
            drawing.add(tri);
            drawing.add(cir);
            drawing.draw("Green");
 
            Console.ReadKey();
        }
    }
}

In the client, we add figures and change the color of all added figures to the list by the draw() method.

Result

compositethird.png

Relations with other design patterns

  1. Composite and decorator have similar schemes, because both are designed to organize a specific number of objects.
  2. Flyweight is often combined with the Composite to implement shared leaf nodes.

Summary

That’s all about Composite 🙂.

As you can see, the composite is not so difficult. To sum up, the composite pattern makes it easier to operate on the hierarchy of objects, without losing access to individual objects that constitute a group, it gives the impression that we operated on a single object, in fact we operate on a group of objects.

I hope that I have explained the composite pattern well enough and that from now on you will be using it easily in your projects 🙂

Link to github with the whole code from this article: https://github.com/Slaw145/CompositeTutorial

This content also you can find on my blog http://devman.pl/programtech/design-patterns-composite/

If you recognise it as useful, share it with others so that others can also use it.

Leave upvote and follow and wait for next articles :) .

In the next article, we will talk about the Bridge pattern.

And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂

– site on fb: Devman.pl-Sławomir Kowalski

– group on fb: DevmanCommunity

Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!