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.
NOTES
In this article, we discuss the implementation of the Composite Pattern in Java.
See the composite in other languages in the “Other Code Implementations” section. Or, use the link below to check the details of the Composite Pattern-
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.