w3resource

Kotlin Composite Pattern: Building hierarchical structures


Write a Kotlin object-oriented program that implements the composite pattern by creating a base class Component and composite classes CompositeComponent and BranchComponent to represent a hierarchical structure.


Pre-Knowledge (Before You Start!)

Before attempting this exercise, you should be familiar with the following concepts:

  • Abstract Classes: Understanding how to define abstract classes with both concrete and abstract methods.
  • Composite Pattern: The Composite Pattern allows you to represent part-whole hierarchies where individual objects and compositions of objects are treated uniformly.
  • Inheritance and Overriding: How to create subclasses that extend an abstract base class and override methods to implement their specific behavior.
  • Mutable List: Using a mutable list to manage a collection of child components in a composite structure.
  • Recursive Method Calls: Using recursion within the display method to traverse and print out the entire hierarchical structure.

Hints (Try Before Looking at the Solution!)

Try to solve the problem using these hints:

  • Hint 1: Define an abstract base class Component with a display method.
  • Hint 2: Create a CompositeComponent class that extends Component and contains a list of child components. Implement methods for adding and removing components.
  • Hint 3: Override the display method in CompositeComponent to print the component name and recursively call display on its children.
  • Hint 4: Create a BranchComponent class that extends Component and overrides display to print only the branch component name.
  • Hint 5: In the main function, create instances of CompositeComponent and BranchComponent to build a hierarchical structure and call display to visualize it.

Sample Solution:

Kotlin Code:

abstract class Component(val name: String) {
    abstract fun display()
}

class CompositeComponent(name: String) : Component(name) {
    private val components: MutableList = mutableListOf()

    fun add(component: Component) {
        components.add(component)
    }

    fun remove(component: Component) {
        components.remove(component)
    }

    override fun display() {
        println("Composite Component: $name")
        components.forEach { component ->
            component.display()
        }
    }
}

class BranchComponent(name: String) : Component(name) {
    override fun display() {
        println("Branch Component: $name")
    }
}

fun main() {
    val headOffice = CompositeComponent("Head Office")
    val region1 = CompositeComponent("Region 1")
    val region2 = CompositeComponent("Region 2")
    val branch1 = BranchComponent("Bracnch 1")
    val branch2 = BranchComponent("Bracnch 2")
    val branch3 = BranchComponent("Branch 3")

    headOffice.add(region1)
    headOffice.add(region2)
    region1.add(branch1)
    region1.add(branch2)
    region2.add(branch3)

    headOffice.display()
}

Sample Output:

Composite Component: Head Office
Composite Component: Region 1
Branch Component: Bracnch 1
Branch Component: Bracnch 2
Composite Component: Region 2
Branch Component: Branch 3

Explanation:

In the above exercise -

  • The "Component" class is an abstract class with a name property and an abstract display function. It serves as the base component for both region and composite components.
  • The "CompositeComponent" class extends the Component class and represents a composite component. It has a list of child components (components) and provides methods to add and remove components. The display function is overridden to display the composite component name and recursively calls the display function on its child components.
  • The "BranchComponent" class also extends the Component class and represents a leaf component. It overrides the display function to display the branch component name.
  • In the "main()" function, we create instances of CompositeComponent (e.g., headOffice, region1, region2) and BranchComponent (e.g., branch1, branch2, branch3) to represent a hierarchical structure. We add the branch components to the region components, and the region components to the head office component.
  • Finally, we call the "display()" function on the headOffice instance, which triggers the recursive display of the entire hierarchical structure, starting from the head office.

Kotlin Editor:


Previous: Creating animal instances.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.