Design Pattern: Composite Pattern

Summary

Pattern NameComposite Pattern
Pattern TypeStructural Pattern
ScopeObject
TaglineHandle list of objects (compositions) of the same interface together
Use casesWhen objects of the same type need to be handled together
and the handling class needs to implement the same interface
Related PatternsDecorator
Iterator
Flyweight
Visitor
Difficulty LevelEasy
Implementations

Definition

When there is a bunch of classes that are of the same type (implement the same interface), and we need to use them as composition (not as individual objects), we can use Composite pattern. Composite pattern helps to use the classes in a composition, so that the client can use the composition and individual classes can be tread in the same way.

Implementation

Composite pattern has 3 parts.

  1. Component: this is the interface that all classes implement so that the composition of classes can work.
  2. Leaf: these are the individual classes.
  3. Composite: this class implements the same interface as the leaf, and handles the composition/leaf/group of individual classes.

Use the following steps and criteria to implement Composite pattern.

  1. Create an interface, that the leaf classes and composite class will implement.
  2. Implement the interface for all the Leaf classes. Leaf classes do not have any reference to other classes.
  3. Create a composite class.
  4. Maintain a list of Leaf objects in the composite class.
  5. Implement methods to add and remove Leaf objects in the composite class.
  6. Implement the base interface for composite class.
  7. In the composite class, the implemented methods will call the methods of all Leaf objects in the list (in loops).
  8. In the client add/remove the Leaf object in the list of composite classes, then call the functions of the composite class when required.

Examples

Example #1: Transport Composite List

Let’s consider a transport system in an application. Take a look at the class diagram first:

Here we have different transport available – car, bike, plane. We will use the composite pattern (using TransportGroup class) to handle a list/group of transports.

Transport Interface

interface Transport

    function start()

    function operate()

    function stop()

end interface

Bike Class

class Bike implements Transport
    
    function start()
        print "Starting Bike..."
    end function

    function operate()
        print "Riding Bike"
    end function

    function stop()
        print "Stopping Bike..."
    end function

end class

Plane Class

class Plane implements Transport
    
    function start()
        print "Starting Plane..."
    end function

    function operate()
        print "Flying Plane"
    end function

    function stop()
        print "Stopping Plane..."
    end function

end class

Car Class

class Car implements Transport

    function start()
        print "Starting Car..."
    end function

    function operate()
        print "Driving Car"
    end function

    function stop()
        print "Stopping Car..."
    end function

end class

Composite Class

class TransportGroup implements Transport

    var transportList: Transport[]    // Maintain a list of Transport Leaf classes

    // Override start of Transport interface
    function start()
        loop transportList as transport
            transport.start()
        end loop
    end function

    // Override operate of Transport interface
    function operate()
        loop transportList as transport
            transport.operate()
        end loop
    end function

    // Override stop of Transport interface
    function stop()
        loop transportList as transport
            transport.stop()
        end loop
    end function

    function addTransport(Transport transport)
        // Add object to list
        transportList.add(transport)
    end function

    function removeTransport(Transport transport) {
        // Remove object from list
        transportList.remove(transport)
    end function

end class

Demo

var bike: Bike = new Bike()
var plane: Plane = new Plane()
var car: Car = new Car()
var secondCar: Car = new Car()

TransportGroup transports = new TransportGroup()

// Add 4 transports
transports.addTransport(bike)
transports.addTransport(plane)
transports.addTransport(car)
transports.addTransport(secondCar)

// Perform operation of the list of 4 transports
transports.start()
transports.operate()
transports.stop()

// Remove plane and perform operations on other transports
transports.removeTransport(plane)

transports.start()
transports.operate()
transports.stop()

Output

The output of the demo above will be like below.

-----------------Output with 4 transports------------------

Starting Bike...
Starting Plane...
Starting Car...
Starting Car...
Riding Bike
Flying Plane
Driving Car
Driving Car
Stopping Bike...
Stopping Plane...
Stopping Car...
Stopping Car...

-----------------Output when plane is removed------------------

Starting Bike...
Starting Car...
Starting Car...
Riding Bike
Driving Car
Driving Car
Stopping Bike...
Stopping Car...
Stopping Car...

Code Implementations

Use the following links to check Composite pattern implementation in specific programming languages.

Leave a Comment