Composite Design Pattern in R

1. Definition

The Composite Design Pattern composes objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions of objects uniformly.

2. Problem Statement

Imagine you are designing a system to represent a file directory structure where a directory can contain files or other directories. How would you design your system such that treating individual files and directories (which can contain files or other directories) can be done uniformly?

3. Solution

Use the Composite Design Pattern. In this pattern, both individual objects (Files) and composite objects (Directories) will share the same interface. This makes it easier to treat them uniformly.

4. Real-World Use Cases

1. Graphic systems where shapes can be made up of simpler shapes.

2. Organizational structures where an employee can be a manager or a simple employee, but both have the same operations like 'getSalary'.

3. File directory systems, as mentioned in the problem above.

5. Implementation Steps

1. Define a component interface that will be implemented by all concrete components (both leaf and composite).

2. Create leaf components that implement the component interface.

3. Create composite components that also implement the component interface, and can contain leaf or other composite components.

6. Implementation in R Programming

# Step 1: Component Interface
Component <- function() {
  list(
    display = function() {
      stop("Abstract method. Implement in concrete components.")
    }
  )
}
# Step 2: Leaf Components
File <- function(name) {
  component <- Component()
  component$display <- function() {
    return(paste("File:", name))
  }
  return(component)
}
# Step 3: Composite Components
Directory <- function(name) {
  component <- Component()
  children <- list()
  component$add <- function(child) {
    children <<- c(children, list(child))
  }
  component$display <- function() {
    output <- paste("Directory:", name)
    for (child in children) {
      output <- paste(output, "\n", child$display())
    }
    return(output)
  }
  return(component)
}
# Client Code
rootDir <- Directory("Root")
dir1 <- Directory("Dir1")
file1 <- File("File1.txt")
file2 <- File("File2.txt")
dir1$add(file1)
rootDir$add(dir1)
rootDir$add(file2)
output <- rootDir$display()

Output:

Directory: Root
 Directory: Dir1
  File: File1.txt
 File: File2.txt

Explanation:

1. We start with a common Component interface that both individual File and composite Directory objects will implement.

2. The File object, being a leaf, implements the display method to show its name.

3. The Directory object, being a composite, can hold other File or Directory objects and recursively call their display method.

4. The client code demonstrates creating a directory structure and displaying it. Both files and directories are treated uniformly due to the shared interface.

7. When to use?

Use the Composite Pattern when:

1. You have to implement tree-like structures.

2. You want the client code to treat both simple and complex elements uniformly.

3. You want to unify the treatment of individual objects and their compositions.

This pattern provides great flexibility and simplifies the client code as it doesn't need to distinguish between simple and composite objects.


Comments