Implementing the decorator pattern in Kotlin.

Kotlin makes it easier to implement the decorator pattern by using the “by” keyword

Lets take my favourite example from the book Head First Design Pattern of the decorator pattern starbuz coffee

Here the author describes a fictitious coffee shop where the Base beverage is decorated by various kinds of Condiments to make the final beverage.

To make a perfect mocha

1 cup of brewed coffee(Dark Roast) 2 servings of your favorite chocolate bar shavings or cocoa powder (roughly 1/4 cup) a serving of whipped cream (I know this is a terrible mocha)

Now some people may want 4 servings of Cocoa powder, some people don’t like whipped cream :(

Now Starbuzz coffee should be able to accomodate such changes and calculate the cost and description accurately.

The Decorator pattern is a perfect use case here, make your base beverage and then decorate it with your favorite condiments, perfect …

The essence of the pattern is that a new class is created, implementing the same interface as the original class and storing the instance of the original class as a field. Methods in which the behavior of the original class doesn’t need to be modified are forwarded to the original class instance.”

Excerpt From: Dmitry Jemerov Svetlana Isakova. “Kotlin in Action.

class DelegatingCollection<T> : Collection<T> {
    private val innerList = arrayListOf<T>()

    override val size: Int get() = innerList.size
    override fun isEmpty(): Boolean = innerList.isEmpty()
    override fun contains(element: T): Boolean = innerList.contains(element)
    override fun iterator(): Iterator<T> = innerList.iterator()
    override fun containsAll(elements: Collection<T>): Boolean =
            innerList.containsAll(elements)
}

Kotlin eliminates all these additional methods because you can just write

class DelegatingCollection<T>(
        innerList: Collection<T> = ArrayList<T>()
) : Collection<T> by innerList {}

Coming back to Starbuzz coffee example here is some code that implements this problem using the decorator pattern in Kotlin


interface Beverage {

    var desription: String

    fun getDescription(): String = "Unknown beverage"

    fun cost(): Double
}


interface CondimentDecorator : Beverage {
    override fun getDescription(): String
}

class Espresso : Beverage {
    override var desription: String
        get() = "Espresso"
        set(value) {}

    override fun cost(): Double {
        return 1.99
    }


}

class HouseBlend : Beverage {
    override var desription: String
        get() = "HouseBlend"
        set(value) {}

    override fun cost(): Double {
        return 0.89
    }

}

class DarkRoast : Beverage {
    override fun getDescription(): String {
        return desription
    }

    override var desription: String
        get() = "DarkRoast"
        set(value) {}

    override fun cost(): Double {
        return 0.69
    }

}

class CocoaPowder(val beverage: Beverage):CondimentDecorator,Beverage by beverage
{
    override fun cost(): Double {
        return beverage.cost() +  0.20
    }

    override fun getDescription(): String {
        return beverage.getDescription()+" and 1 serving of Cocoa Powder"
    }

}

class Whip(val beverage: Beverage):CondimentDecorator,Beverage by beverage
{
    override fun cost(): Double {
        return beverage.cost() +  0.10
    }

    override fun getDescription(): String {
        return beverage.getDescription()+" and serving of whipped cream"
    }

}

fun main(args: Array<String>) {
    println("Starbuzzz Coffee")
    var dr:Beverage = DarkRoast()
    dr= CocoaPowder(dr)
    dr= CocoaPowder(dr)
    dr=Whip(dr)
    println("""The cost of the beverage with ingredients:
        |${dr.getDescription()} has cost of: $${dr.cost()}""".trimMargin())
}



Running this will give the following output

Starbuzzz Coffee
The cost of the beverage with ingredients:
DarkRoast and 1 serving of Cocoa Powder and 1 serving of Cocoa Powder and serving of whipped cream has cost of: $1.19