Composite Design Pattern example in Java

Imagine you are building a project management system where tasks can be either simple tasks or a collection of tasks (subtasks) forming a larger task.

1. Task (Component)

  • Represents the common interface for both simple tasks and task lists.
  • Defines methods such as getTitle(), setTitle(), and display().

Java




// Component
 
public interface Task {
    String getTitle();
    void setTitle(String title);
    void display();
}


2. SimpleTask (Leaf)

  • Represents an individual task with a title.
  • Implements the Task interface.

Java




// Leaf
 
public class SimpleTask implements Task {
    private String title;
 
    public SimpleTask(String title) {
        this.title = title;
    }
 
    @Override
    public String getTitle() {
        return title;
    }
 
    @Override
    public void setTitle(String title) {
        this.title = title;
    }
 
    @Override
    public void display() {
        System.out.println("Simple Task: " + title);
    }
}


3. TaskList (Composite)

  • Represents a collection of tasks, which can include both simple tasks and other task lists.
  • Implements the Task interface but also has a list of tasks (List<Task>).
  • Defines methods to add, remove, and display tasks.

Java




import java.util.ArrayList;
import java.util.List;
 
// Composite
 
public class TaskList implements Task {
    private String title;
    private List<Task> tasks;
 
    public TaskList(String title) {
        this.title = title;
        this.tasks = new ArrayList<>();
    }
 
    @Override
    public String getTitle() {
        return title;
    }
 
    @Override
    public void setTitle(String title) {
        this.title = title;
    }
 
    public void addTask(Task task) {
        tasks.add(task);
    }
 
    public void removeTask(Task task) {
        tasks.remove(task);
    }
 
    @Override
    public void display() {
        System.out.println("Task List: " + title);
        for (Task task : tasks) {
            task.display();
        }
    }
}


4. TaskManagementApp (Client)

  • Represents the application that uses the Composite Design Pattern to manage tasks.
  • It creates a mix of simple tasks and task lists, showcasing how the Composite pattern allows treating both individual tasks and task collections uniformly.
  • The created tasks are displayed in a hierarchical structure to illustrate the pattern’s flexibility and uniform handling of different task types.

Java




// Client
 
public class TaskManagementApp {
    public static void main(String[] args) {
        // Creating simple tasks
        Task simpleTask1 = new SimpleTask("Complete Coding");
        Task simpleTask2 = new SimpleTask("Write Documentation");
 
        // Creating a task list
        TaskList projectTasks = new TaskList("Project Tasks");
        projectTasks.addTask(simpleTask1);
        projectTasks.addTask(simpleTask2);
 
        // Nested task list
        TaskList phase1Tasks = new TaskList("Phase 1 Tasks");
        phase1Tasks.addTask(new SimpleTask("Design"));
        phase1Tasks.addTask(new SimpleTask("Implementation"));
 
        projectTasks.addTask(phase1Tasks);
 
        // Displaying tasks
        projectTasks.display();
    }
}


Complete code for the above example:

This code includes the Task, SimpleTask, TaskList, and TaskManagementApp classes. It demonstrates the Composite Design Pattern for organizing tasks in a project management system.

Java




import java.util.ArrayList;
import java.util.List;
 
// Component
interface Task {
    String getTitle();
    void setTitle(String title);
    void display();
}
 
// Leaf
class SimpleTask implements Task {
    private String title;
 
    public SimpleTask(String title) {
        this.title = title;
    }
 
    @Override
    public String getTitle() {
        return title;
    }
 
    @Override
    public void setTitle(String title) {
        this.title = title;
    }
 
    @Override
    public void display() {
        System.out.println("Simple Task: " + title);
    }
}
 
// Composite
class TaskList implements Task {
    private String title;
    private List<Task> tasks;
 
    public TaskList(String title) {
        this.title = title;
        this.tasks = new ArrayList<>();
    }
 
    @Override
    public String getTitle() {
        return title;
    }
 
    @Override
    public void setTitle(String title) {
        this.title = title;
    }
 
    public void addTask(Task task) {
        tasks.add(task);
    }
 
    public void removeTask(Task task) {
        tasks.remove(task);
    }
 
    @Override
    public void display() {
        System.out.println("Task List: " + title);
        for (Task task : tasks) {
            task.display();
        }
    }
}
 
// Client
public class TaskManagementApp {
    public static void main(String[] args) {
        // Creating simple tasks
        Task simpleTask1 = new SimpleTask("Complete Coding");
        Task simpleTask2 = new SimpleTask("Write Documentation");
 
        // Creating a task list
        TaskList projectTasks = new TaskList("Project Tasks");
        projectTasks.addTask(simpleTask1);
        projectTasks.addTask(simpleTask2);
 
        // Nested task list
        TaskList phase1Tasks = new TaskList("Phase 1 Tasks");
        phase1Tasks.addTask(new SimpleTask("Design"));
        phase1Tasks.addTask(new SimpleTask("Implementation"));
 
        projectTasks.addTask(phase1Tasks);
 
        // Displaying tasks
        projectTasks.display();
    }
}


Output

Task List: Project Tasks
Simple Task: Complete Coding
Simple Task: Write Documentation
Task List: Phase 1 Tasks
Simple Task: Design
Simple Task: Implementation



Composite Design Pattern in Java

The Composite Design Pattern is a structural design pattern that lets you compose objects into tree-like structures to represent part-whole hierarchies. It allows clients to treat individual objects and compositions of objects uniformly. In other words, whether dealing with a single object or a group of objects (composite), clients can use them interchangeably.

As described by the Gang of four, “Compose objects into tree structure to represent part-whole hierarchies. Composite lets client treat individual objects and compositions of objects uniformly”.

The key concept is that you can manipulate a single instance of the object just as you would manipulate a group of them. The operations you can perform on all the composite objects often have the least common denominator relationship.

Important Topics for the Composite Design Pattern in Java

  • Components of Composite Design Pattern
  • Composite Design Pattern example in Java
  • Why do we need Composite Design Pattern?
  • When to use Composite Design Pattern?
  • When not to use Composite Design Pattern?

Similar Reads

Components of Composite Design Pattern

...

Composite Design Pattern example in Java

Imagine you are building a project management system where tasks can be either simple tasks or a collection of tasks (subtasks) forming a larger task....

Why do we need Composite Design Pattern?

...

When to use Composite Design Pattern?

...

When not to use Composite Design Pattern?

...