w3resource

Kotlin decorator pattern: Modifying component behavior


Write a Kotlin object-oriented program that implements the decorator pattern by creating a base class Component and decorator classes BoldDecorator and ItalicDecorator to modify the behavior of the component.


Pre-Knowledge (Before You Start!)

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

  • Interfaces: Understanding how to define and implement interfaces in Kotlin.
  • Decorator Pattern: A structural design pattern that allows behavior to be added to objects dynamically without modifying their existing code.
  • Inheritance: How to create a base class and extend it using subclasses.
  • Super Keyword: Using super to call methods from a parent class.
  • Composition: Instead of modifying a class directly, using another class to wrap and extend its functionality.

Hints (Try Before Looking at the Solution!)

Try to solve the problem using these hints:

  • Hint 1: Define a Component interface with a method render() that returns a string.
  • Hint 2: Create a ConcreteComponent class that implements the Component interface and provides a basic implementation of render().
  • Hint 3: Create an abstract decorator class TextDecorator that implements the Component interface and delegates the render() method to the wrapped component.
  • Hint 4: Implement a BoldDecorator that overrides the render() method to wrap text in <b> ... </b>.
  • Hint 5: Implement an ItalicDecorator that overrides the render() method to wrap text in <i> ... </i>.
  • Hint 6: In the main() function, create instances of the decorators and wrap them around the ConcreteComponent to test different formatting options.

Sample Solution:

Kotlin Code:

interface Component {
    fun render(): String
}

class ConcreteComponent : Component {
    override fun render(): String {
        return "Original component: Kotlin OOP"
    }
}

abstract class TextDecorator(private val component: Component) : Component {
    override fun render(): String {
        return component.render()
    }
}

class BoldDecorator(component: Component) : TextDecorator(component) {
    override fun render(): String {
        val renderedText = super.render()
        return "<b>$renderedText</b>"
    }
}

class ItalicDecorator(component: Component) : TextDecorator(component) {
    override fun render(): String {
        val renderedText = super.render()
        return "<i>$renderedText</i>"
    }
}

fun main() {
    val originalComponent: Component = ConcreteComponent()
    val boldDecorator: Component = BoldDecorator(originalComponent)
    val italicDecorator: Component = ItalicDecorator(originalComponent)
    val boldItalicDecorator: Component = ItalicDecorator(BoldDecorator(originalComponent))

    println("Original: ${originalComponent.render()}")
    println("Bold Decorator: ${boldDecorator.render()}")
    println("Italic Decorator: ${italicDecorator.render()}")
    println("Bold Italic Decorator: ${boldItalicDecorator.render()}")
}

Sample Output:

Original: Original component: Kotlin OOP
Bold Decorator: <b>Original component: Kotlin OOP</b>
Italic Decorator: <i>Original component: Kotlin OOP</i>
Bold Italic Decorator: <i><b>Original component: Kotlin OOP</b></i>

Explanation:

In the above exercise -

  • We have an interface Component that defines the common behavior for all components. The ConcreteComponent class implements the Component interface, representing the original component.
  • "TextDecorator" is an abstract class that implements the Component interface and holds a reference to another component. It acts as a base class for specific decorators.
  • "BoldDecorator" and "ItalicDecorator" are concrete decorator classes that extend "TextDecorator". They override the render() method to modify the wrapped component's behavior. In this case, they add HTML tags <b> and <i> to the rendered text.
  • In the main() function, we create instances of the original component and different decorators. The decorators modify the original component's behavior by calling render() on each of them.

Kotlin Editor:


Previous: Handling operation results.
Next: 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.