Open In App
Related Articles

Composite Design Pattern

Improve Article
Improve
Save Article
Save
Like Article
Like

Composite pattern is a partitioning design pattern and describes a group of objects that is treated the same way as a single instance of the same type of object. The intent of a composite is to “compose” objects into tree structures to represent part-whole hierarchies. It allows you to have a tree structure and ask each node in the tree structure to perform a task.

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

When dealing with Tree-structured data, programmers often have to discriminate between a leaf-node and a branch. This makes code more complex, and therefore, error prone. The solution is an interface that allows treating complex and primitive objects uniformly.

In object-oriented programming, a composite is an object designed as a composition of one-or-more similar objects, all exhibiting similar functionality. This is known as a “has-a” relationship between objects.

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 a least common denominator relationship.

The Composite Pattern has four participants:

Component – Component declares the interface for objects in the composition and for accessing and managing its child components. It also implements default behavior for the interface common to all classes as appropriate.

Leaf – Leaf defines behavior for primitive objects in the composition. It represents leaf objects in the composition.

Composite – Composite stores child components and implements child related operations in the component interface.

Client – Client manipulates the objects in the composition through the component interface.

Client use the component class interface to interact with objects in the composition structure. If recipient is a leaf then request is handled directly. If recipient is a composite, then it usually forwards request to its child components, possibly performing additional operations before and after forwarding.

Real Life example

In an organization, It have general managers and under general managers, there can be managers and under managers there can be developers. Now you can set a tree structure and ask each node to perform common operation like getSalary(). Composite design pattern treats each node in two ways: 1)

Composite

– Composite means it can have other objects below it. 2)

leaf

– leaf means it has no objects below it.

Tree structure:

Tree

The above figure shows a typical Composite object structure. As you can see, there can be many children to a single parent i.e. Composite, but only one parent per child.

Interface Component.java

Java




public interface Employee
{
    public void showEmployeeDetails();
}


Leaf.java

Java




public class Developer implements Employee
{
    private String name;
    private long empId;
    private String position;
 
    public Developer(long empId, String name, String position)
    {
        this.empId = empId;
        this.name = name;
                this.position = position;
    }
     
    @Override
    public void showEmployeeDetails()
    {
        System.out.println(empId+" " +name+);
    }
}


Leaf.java

Java




public class Manager implements Employee
{
    private String name;
    private long empId;
        private String position;
 
    public Manager(long empId, String name, String position)
    {
        this.empId = empId;
        this.name = name;
                this.position = position;
    }
     
    @Override
    public void showEmployeeDetails()
    {
        System.out.println(empId+" " +name);
    }
}


Composite.java

Java




import java.util.ArrayList;
import java.util.List;
 
public class CompanyDirectory implements Employee
{
    private List<Employee> employeeList = new ArrayList<Employee>();
      
    @Override
    public void showEmployeeDetails()
    {
        for(Employee emp:employeeList)
        {
            emp.showEmployeeDetails();
        }
    }
      
    public void addEmployee(Employee emp)
    {
        employeeList.add(emp);
    }
      
    public void removeEmployee(Employee emp)
    {
        employeeList.remove(emp);
    }
}


Client.java

Java




public class Company
{
    public static void main (String[] args)
    {
        Developer dev1 = new Developer(100, "Lokesh Sharma", "Pro Developer");
        Developer dev2 = new Developer(101, "Vinay Sharma", "Developer");
        CompanyDirectory engDirectory = new CompanyDirectory();
        engDirectory.addEmployee(dev1);
        engDirectory.addEmployee(dev2);
         
        Manager man1 = new Manager(200, "Kushagra Garg", "SEO Manager");
        Manager man2 = new Manager(201, "Vikram Sharma ", "Kushagra's Manager");
         
        CompanyDirectory accDirectory = new CompanyDirectory();
        accDirectory.addEmployee(man1);
        accDirectory.addEmployee(man2);
     
        CompanyDirectory directory = new CompanyDirectory();
        directory.addEmployee(engDirectory);
        directory.addEmployee(accDirectory);
        directory.showEmployeeDetails();
    }
}


UML Diagram for the Composite Design Pattern :

Composite-Design-UML

Full Running Code for the above example :

Java




// A Java program to demonstrate working of
// Composite Design Pattern with example
// of a company with different
//  employee details
 
import java.util.ArrayList;
import java.util.List;
 
 
// A common interface for all employee
interface Employee
{
    public void showEmployeeDetails();
}
 
class Developer implements Employee
{
    private String name;
    private long empId;
    private String position;
     
    public Developer(long empId, String name, String position)
    {
        // Assign the Employee id,
        // name and the position
        this.empId = empId;
        this.name = name;
        this.position = position;
    }
     
    @Override
    public void showEmployeeDetails()
    {
        System.out.println(empId+" " +name+ " " + position );
    }
}
 
class Manager implements Employee
{
    private String name;
    private long empId;
    private String position;
  
    public Manager(long empId, String name, String position)
    {
        this.empId = empId;
        this.name = name;
        this.position = position;
    }
      
    @Override
    public void showEmployeeDetails()
    {
        System.out.println(empId+" " +name+ " " + position );
    }
}
 
 
// Class used to get Employee List
// and do the opertions like
// add or remove Employee
 
class CompanyDirectory implements Employee
{
    private List<Employee> employeeList = new ArrayList<Employee>();
       
    @Override
    public void showEmployeeDetails()
    {
        for(Employee emp:employeeList)
        {
            emp.showEmployeeDetails();
        }
    }
       
    public void addEmployee(Employee emp)
    {
        employeeList.add(emp);
    }
       
    public void removeEmployee(Employee emp)
    {
        employeeList.remove(emp);
    }
}
 
// Driver class
public class Company
{
    public static void main (String[] args)
    {
        Developer dev1 = new Developer(100, "Lokesh Sharma", "Pro Developer");
        Developer dev2 = new Developer(101, "Vinay Sharma", "Developer");
        CompanyDirectory engDirectory = new CompanyDirectory();
        engDirectory.addEmployee(dev1);
        engDirectory.addEmployee(dev2);
          
        Manager man1 = new Manager(200, "Kushagra Garg", "SEO Manager");
        Manager man2 = new Manager(201, "Vikram Sharma ", "Kushagra's Manager");
          
        CompanyDirectory accDirectory = new CompanyDirectory();
        accDirectory.addEmployee(man1);
        accDirectory.addEmployee(man2);
      
        CompanyDirectory directory = new CompanyDirectory();
        directory.addEmployee(engDirectory);
        directory.addEmployee(accDirectory);
        directory.showEmployeeDetails();
    }
}


Output :

100 Lokesh Sharma Pro Developer
101 Vinay Sharma Developer
200 Kushagra Garg SEO Manager
201 Vikram Sharma Kushagra's Manager

When to use Composite Design Pattern?

Composite Pattern should be used when clients need to ignore the difference between compositions of objects and individual objects. If programmers find that they are using multiple objects in the same way, and often have nearly identical code to handle each of them, then composite is a good choice, it is less complex in this situation to treat primitives and composites as homogeneous.

Less number of objects reduces the memory usage, and it manages to keep us away from errors related to memory like java.lang.OutOfMemoryError.

Although creating an object in Java is really fast, we can still reduce the execution time of our program by sharing objects.

When not to use Composite Design Pattern?

Composite Design Pattern makes it harder to restrict the type of components of a composite. So it should not be used when you don’t want to represent a full or partial hierarchy of objects.

Composite Design Pattern can make the design overly general. It makes harder to restrict the components of a composite. Sometimes you want a composite to have only certain components. With Composite, you can’t rely on the type system to enforce those constraints for you. Instead you’ll have to use run-time checks.

Further Read: Composite Method in PythonIf you like GeeksforGeeks and would like to contribute, you can also write an article using

write.geeksforgeeks.org

or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.


Whether you're preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, GeeksforGeeks Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we've already empowered, and we're here to do the same for you. Don't miss out - check it out now!

Last Updated : 07 Nov, 2023
Like Article
Save Article
Previous
Next
Similar Reads