Design Pattern: Composite Pattern in Java

Composite pattern is used to handle the operation of a bunch of classes (having the same interface), to operate the same function of all items at the same time. Using Composite pattern the client can ignore the difference between the Composition and Leaf classes, and can use the composition considering the same interface.

This article demonstrates Composite pattern implementations in Java. Check the following examples.

Examples

Check the following examples, which demonstrates Composite pattern in Java-

Example #1: Transport List

In the example below we are implementing the Composite pattern for a transport system.

Take a look at the class diagram.

Transport Interface

Let’s define an interface that will be used by both individual transport objects and the object group class.

// Transport.java

package com.bigboxcode.designpattern.composite.transport;

public interface Transport {

    void start();

    void operate();

    void stop();

}

Bike Class

Class for bike implementing the Transport interface.

// Bike.java

package com.bigboxcode.designpattern.composite.transport;

public class Bike implements Transport{
    @Override
    public void start() {
        System.out.println("Starting Bike...");
    }

    @Override
    public void operate() {
        System.out.println("Riding Bike");
    }

    @Override
    public void stop() {
        System.out.println("Stopping Bike...");
    }
}

Plane Class

Class for Plane implementing the Transport interface.

// Plane.java

package com.bigboxcode.designpattern.composite.transport;

public class Plane implements Transport {
    @Override
    public void start() {
        System.out.println("Starting Plane...");
    }

    @Override
    public void operate() {
        System.out.println("Flying Plane");
    }

    @Override
    public void stop() {
        System.out.println("Stopping Plane...");
    }
}

Car Class

Class for Car, which implements the Transport interface.

// Car.java

package com.bigboxcode.designpattern.composite.transport;

public class Car implements Transport {
    @Override
    public void start() {
        System.out.println("Starting Car...");
    }

    @Override
    public void operate() {
        System.out.println("Driving Car");
    }

    @Override
    public void stop() {
        System.out.println("Stopping Car...");
    }
}

Composite Class

Composite class, which stores a list of different types of transports (of type Transport) and also implements the Transport interface.

As a result of the Transport interface implementation, it has to implement the functions – start(), stop(), operate(). In those operations, the class performs the operation on the list of transport objects.

A few additional methods may be required, for adding and/or removing elements to the list of objects.

// TransportGroup.java

package com.bigboxcode.designpattern.composite.transport;

import java.util.ArrayList;
import java.util.List;

public class TransportGroup implements Transport {
    private List<Transport> transportList = new ArrayList<Transport>();

    @Override
    public void start() {
        for (Transport transport: transportList) {
            transport.start();
        }
    }

    @Override
    public void operate() {
        for (Transport transport: transportList) {
            transport.operate();
        }
    }

    @Override
    public void stop() {
        for (Transport transport: transportList) {
            transport.stop();
        }
    }

    public void addTransport(Transport transport) {
        transportList.add(transport);
    }

    public void removeTransport(Transport transport) {
        transportList.remove(transport);
    }
}

Demo

While using the implementation above, the client will treat the individual classes and the composite class object the same way. The client does not know any difference between those as both implement the same interface.

// Demo.java

package com.bigboxcode.designpattern.composite.transport;

public class Demo {
    public static void main(String[] args) {
        Bike bike = new Bike();
        Plane plane = new Plane();
        Car car = new Car();
        Car secondCar = new Car();

        TransportGroup transports = new TransportGroup();
        transports.addTransport(bike);
        transports.addTransport(plane);
        transports.addTransport(car);
        transports.addTransport(secondCar);

        System.out.println("-----------------Output with 4 transports------------------\n");

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

        System.out.println("\n-----------------Output when plane is removed------------------\n");

        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...

Example #2: Player Group

Let’s consider a system where we want to store players. players from different teams and ages can be there.

Player Interface

// Player.java

package com.bigboxcode.designpattern.composite.player;

public interface Player {

    void printDetails();

}

Basketball Player Class

// BasketballPlayer.java

package com.bigboxcode.designpattern.composite.player;

public class BasketBallPlayer implements Player {
        private String name;
        private int age;

        private int point;

    public BasketBallPlayer(String name, int age, int point) {
        this.name = name;
        this.age = age;
        this.point = point;
    }

    @Override
    public void printDetails() {
        System.out.println("Game: Basketball");
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Points: " + point);
    }
}

Football Player Class

// FootballPlayer.java

package com.bigboxcode.designpattern.composite.player;

public class FootballPlayer implements Player {
    private String name;
    private int age;

    private int goal;

    public FootballPlayer(String name, int age, int goal) {
        this.name = name;
        this.age = age;
        this.goal = goal;
    }

    @Override
    public void printDetails() {
        System.out.println("Game: Football");
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Goals: " + goal);
    }
}

Cricket Player Class

// CricketPlayer.java

package com.bigboxcode.designpattern.composite.player;

public class CricketPlayer implements Player {
    private String name;
    private int age;

    private int run;

    public CricketPlayer(String name, int age, int run) {
        this.name = name;
        this.age = age;
        this.run = run;
    }

    @Override
    public void printDetails() {
        System.out.println("Game: Cricket");
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Runs: " + run);
    }
}

Player Group Class

package com.bigboxcode.designpattern.composite.player;

import java.util.ArrayList;
import java.util.List;

public class PlayerGroup implements Player {
    private List<Player> playerList = new ArrayList<>();

    @Override
    public void printDetails() {
        for (Player player: playerList) {
            player.printDetails();
        }
    }

    public void addElement(Player transport) {
        playerList.add(transport);
    }

    public void removeElement(Player transport) {
        playerList.remove(transport);
    }
}

Demo

// Demo.java

package com.bigboxcode.designpattern.composite.player;

public class Demo {
    public static void main(String[] args) {

        // Under 15 players
        PlayerGroup under15Players = new PlayerGroup();

        under15Players.addElement(new FootballPlayer("FPlayer 15_1", 13, 23));
        under15Players.addElement(new FootballPlayer("FPlayer 15_2", 14, 30));

        under15Players.addElement(new BasketBallPlayer("BPlayer 15_1", 12, 80));
        under15Players.addElement(new BasketBallPlayer("BPlayer 15_2", 14, 100));

        under15Players.addElement(new CricketPlayer("CPlayer 15_1", 14, 467));


        // Under 19 Players
        PlayerGroup under19Players = new PlayerGroup();

        under19Players.addElement(new FootballPlayer("FPlayer 19_1", 18, 43));

        under19Players.addElement(new BasketBallPlayer("BPlayer 19_1", 17, 77));

        under19Players.addElement(new CricketPlayer("CPlayer 19_1", 18, 654));
        under19Players.addElement(new CricketPlayer("CPlayer 19_2", 16, 789));


        // National team players
        PlayerGroup nationalTeamPlayers = new PlayerGroup();
        nationalTeamPlayers.addElement(new FootballPlayer("FPlayer N_1", 18, 43));
        nationalTeamPlayers.addElement(new BasketBallPlayer("BPlayer N_1", 17, 77));
        nationalTeamPlayers.addElement(new CricketPlayer("CPlayer N_1", 18, 654));


        // Create a group with all teams
        PlayerGroup allTeams = new PlayerGroup();
        allTeams.addElement(under15Players);
        allTeams.addElement(under19Players);
        allTeams.addElement(nationalTeamPlayers);

        // Print details of all players
        // from each game and group
        allTeams.printDetails();
    }
}

Output

Game: Football
Name: FPlayer 15_1
Age: 13
Goals: 23

Game: Football
Name: FPlayer 15_2
Age: 14
Goals: 30

Game: Basketball
Name: BPlayer 15_1
Age: 12
Points: 80

Game: Basketball
Name: BPlayer 15_2
Age: 14
Points: 100

Game: Cricket
Name: CPlayer 15_1
Age: 14
Runs: 467

Game: Football
Name: FPlayer 19_1
Age: 18
Goals: 43

Game: Basketball
Name: BPlayer 19_1
Age: 17
Points: 77

Game: Cricket
Name: CPlayer 19_1
Age: 18
Runs: 654

Game: Cricket
Name: CPlayer 19_2
Age: 16
Runs: 789

Game: Football
Name: FPlayer N_1
Age: 18
Goals: 43

Game: Basketball
Name: BPlayer N_1
Age: 17
Points: 77

Game: Cricket
Name: CPlayer N_1
Age: 18
Runs: 654

Source Code

Use the following link to get the source code:

Other Code Implementations

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

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.