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

Creating objects in so-called tree structures.

Folding objects in such a way that the client sees many of them as one object.

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:

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

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:

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

interfaceIComponent

{

voidoperation();

}

classLeaf:IComponent

{

publicvoidoperation()

{

Console.WriteLine("display leaf "+this);

}

}

classComposite:IComponent

{

privateList<IComponent>_children=newList<IComponent>();

publicvoidoperation()

{

Console.WriteLine("display leaf "+this);

}

publicvoidAddChild(IComponent component)

{

_children.Add(component);

}

publicvoidRemoveChild(IComponent component)

{

_children.Remove(component);

}

publicList<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 🙂

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

staticvoidMain(string[]args)

{

Leaf leaf1=newLeaf();

Leaf leaf2=newLeaf();

Leaf leaf3=newLeaf();

Composite composite=newComposite();

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

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:

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

interfaceIWorker

{

voidDisplayInformationWorker();

}

classWorker:IWorker

{

privatestringFirstName,LastName,Degree;

publicWorker(stringfirstname,stringlastname,stringdegree)

{

FirstName=firstname;

LastName=lastname;

Degree=degree;

}

publicvoidDisplayInformationWorker()

{

Console.WriteLine(FirstName+" "+LastName+" "+Degree);

}

}

classManager:IWorker

{

privatestringFirstName,LastName,Degree;

privateList<IWorker>workers=newList<IWorker>();

publicManager(stringfirstname,stringlastname,stringdegree)

{

FirstName=firstname;

LastName=lastname;

Degree=degree;

}

publicvoidAddWorker(IWorker worker)

{

workers.Add(worker);

}

publicvoidDisplayInformationWorker()

{

Console.WriteLine("Subordinates manager: "+FirstName+" "+LastName);

foreach(IWorker worker inworkers)

{

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:

C#

1

2

3

4

5

6

7

8

9

10

11

staticvoidMain(string[]args)

{

Manager manager=newManager("Andrej","Wardalo","head of the technology department");

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.

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

namespaceShapes

{

publicinterfaceIShape

{

voiddraw(stringfillColor);

}

publicclassTriangle:IShape

{

publicvoiddraw(stringfillColor)

{

Console.WriteLine("Drawing Triangle with color "+fillColor);

}

}

publicclassCircle:IShape

{

publicvoiddraw(stringfillColor)

{

Console.WriteLine("Drawing Circle with color "+fillColor);

}

}

publicclassDrawing:IShape

{

privateList<IShape>shapes=newList<IShape>();

publicvoiddraw(stringfillColor)

{

foreach(IShape sh inshapes)

{

sh.draw(fillColor);

}

}

publicvoidadd(IShapes)

{

shapes.Add(s);

}

publicvoidremove(IShapes)

{

shapes.Remove(s);

}

publicvoidclear()

{

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:

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

namespaceGraphic

{

classProgram

{

staticvoidMain(string[]args)

{

IShape tri=newTriangle();

IShape tri1=newTriangle();

IShape cir=newCircle();

Drawing drawing=newDrawing();

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

Relations with other design patterns

Composite and decorator have similar schemes, because both are designed to organize a specific number of objects.

Flyweight is often combined with the Composite to implement shared leaf nodes.

The iterator can iterate through the composite. Visitor can apply operations in the composite. Composite can use the Responsibility Chain to give components global access through their parent. The composite may use the Decorator to override some parts of the composite. The composite can use the observer pattern to bind one structure to the other and the State to allow the state of the composite to change state.

The composite allows you to create a mediator from smaller pieces through a recursive composition.

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 🙂