1. Definition

The Composite Design Pattern is a structural design pattern that lets you compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

2. Problem Statement

Imagine you are developing a system to represent a graphic drawing, which consists of both simple and complex elements. Simple elements include circles, rectangles, etc., and complex elements are groups of elements that can be further broken down. How can you ensure that client code can treat both simple and complex elements uniformly?

3. Solution

The Composite pattern allows you to use tree structures to build the part-whole hierarchies. Both simple and composite elements share the same interface, which means they can be treated uniformly by the client code.

4. Real-World Use Cases

1. Graphics drawing systems where shapes can be simple or complex.

2. Organizational structures where an employee can be a manager or a general employee.

3. File systems with files and directories.

5. Implementation Steps

1. Define a common interface for both simple and composite objects.

2. Create leaf objects that implement the common interface.

3. Create a composite object which also implements the common interface and stores child components, both simple and composite.

4. Client code can treat both leaf and composite objects uniformly.

6. Implementation

// Step 1: Common Component interface
public interface Graphic {
    void draw();
}

// Step 2: Leaf objects
public class Circle implements Graphic {
    public void draw() {
        System.out.println("Drawing a Circle.");
    }
}

public class Rectangle implements Graphic {
    public void draw() {
        System.out.println("Drawing a Rectangle.");
    }
}

// Step 3: Composite object
import java.util.ArrayList;
import java.util.List;

public class GraphicGroup implements Graphic {
    private List<Graphic> graphics = new ArrayList<Graphic>();

    public void draw() {
        for (Graphic graphic : graphics) {
            graphic.draw();
        }
    }

    public void add(Graphic graphic) {
        graphics.add(graphic);
    }

    public void remove(Graphic graphic) {
        graphics.remove(graphic);
    }
}

// Client Code
public class Client {
    public static void main(String[] args) {
        Circle circle = new Circle();
        Rectangle rectangle = new Rectangle();

        GraphicGroup graphicGroup = new GraphicGroup();

        graphicGroup.add(circle);
        graphicGroup.add(rectangle);

        graphicGroup.draw();
    }
}

Output:

Drawing a Circle.
Drawing a Rectangle.

Explanation:

In the given example, both the simple elements (Circle and Rectangle) and the composite element (GraphicGroup) share the common interface Graphic. This allows us to treat both simple and composite objects uniformly. The GraphicGroup can contain both simple graphics and other graphic groups.

7. When to use?

1. Use the Composite pattern when you need to represent part-whole hierarchies of objects.

2. When you want the client code to treat both simple and composite objects uniformly.

3. When the structure can have any level of depth.