builder-design-pattern-kotlin

Builder Deisgn Pattern in kotlin | Design Patterns

The problem to Solve :

  • Some objects are simple and can be created using single constructor call but there are some constructore which may need more parameter to construct the object.
  • Having more parameters to a constructor is not good approach to handle the product

How Builder Patterns Solves it

  • We create small objects to create the final object
  • Construct a object in multiple pices but making sure end result is same
  • Builder design pattern provids an API for constructing an Object step-by-step
When piecewise object constructon is complicated, provide an API for doing it in simple & clear manner

Let explore normal code without Pattern:

In below example, We are trying to cerate a custom computer which has few components that can be modiefied.

We have a constructor which accepts the number of parameters like OS, RAM, screenSize, ExternalMouse, Battery. So when user want to provide any value


class Computer{
    var OS:String
    var RAM:Int
    var screenSize:Double
    var externalMouse:Boolean
    var externalKeyboard:Boolean
    var battery:String

    constructor(OS: String, RAM: Int, screenSize: Double,
                externalMouse: Boolean, externalKeyboard: Boolean, battery: String) {
        this.OS = OS
        this.RAM = RAM
        this.screenSize = screenSize
        this.externalMouse = externalMouse
        this.externalKeyboard = externalKeyboard
        this.battery = battery
    }

    override fun toString(): String {
        return ("The required configuration is :" +
                "\nOS : $OS " +
                "\nRAM : $RAM " +
                "\nscreenSize : screenSize " +
                "\nexternalMouse : $externalMouse " +
                "\nexternalKeyboard : $externalKeyboard " +
                "\nbattery : $battery"
        )
    }
}

fun main(args: Array<String>) {
    var comp = Computer("Windows", 8, 14.5, true, false, "Inbulit")
    println(comp)
}			

When we want to create a computer with all the configuration then above code will not throw any error. But when we want to order only one or two parameters then also we need to provide all the parameter, where default values for the not required parameter.

This is the issue, all the time you got to provide all the parameters even though you donot need them.

Yeah, I got your point, we can provide in default values in the constructor itself when we are dealing with Kotlin.

Even we can provide so, it will be confusing, when we have more the one parameter with same type in a method/constructor.

To avoid this headache, we have to use the Builder design pattern.

Code with Builder Design Pattern

Now, I have coded something which I call it as Builder design pattern, but you might not think so. So ncase of creection let me know by commenting.

ComputerBuilder :

I have created a class called ComputerBuilder, which has few variable as prive and these are going to be our "Computer parts". User can provide the values for these parts how ever they and it is purely depends on them.

I have created some getters and setters as the variables are private, so no one can access them outside, but we are proovdeing the access through the setter and getters.

								 
open class ComputerBuilder{
    private var OS:String? = null
    private var RAM:Int? = null
    private var screenSize:Double? = null
    private var externalMouse:Boolean? = null
    private var battery:String? = null

    fun setOS(OS:String){
        this.OS = OS
    }
    fun getOS():String?{
        return this.OS
    }
    fun setRAM(RAM:Int){
        this.RAM = RAM
    }
    fun getRAM():Int?{
        return this.RAM
    }
    fun setScreenSize(screenSize:Double){
        this.screenSize = screenSize
    }
    fun getScreenSize():Double?{
        return this.screenSize
    }
    fun setExternalMouse(externalMouse:Boolean){
        this.externalMouse = externalMouse
    }
    fun getExternalMouse():Boolean?{
        return this.externalMouse
    }
    fun setBattery(battery:String){
        this.battery = battery
    }
    fun getBattery():String?{
        return this.battery
    }
}	

Computer :

Even though we recied the configuration in ComputerBuilder object, but we will be building the object on the Computer class.

In computer class we have created the build() function which will make the computer (as of now i am just returning the values in it).

Computer constructor accepts the ComputerBuilder object as parameter an retrives the values from the object

								 
class Computer{

    var cb:ComputerBuilder
    constructor(compBuild:ComputerBuilder) {
        this.cb = compBuild
    }

    fun build():String{

        return ("The required configuration is :" +
                "\nOS : ${cb.getOS()} " +
                "\nRAM : ${cb.getRAM()} " +
                "\nscreenSize : ${cb.getScreenSize()} " +
                "\nexternalMouse : ${cb.getExternalMouse()} " +
                "\nbattery : ${cb.getBattery()}"
                )
    }
}	

main functions

In main function, we are creating the object to ComputerBuilder and we are providng the required configuration for the "computer". and then we pass this object to Computer class object.

								 
fun main(args: Array<String>) {
    var compBuilder = ComputerBuilder()
    compBuilder.setOS("windows")
    compBuilder.setRAM(12)
    compBuilder.setBattery("Inbuilt")
    // not setting any value for external mouse

    var comp = Computer(compBuilder)
    println(comp.build())
}	

Complete code Builder Pattern in kotlin | Design Patterns

								 
open class ComputerBuilder{
    private var OS:String? = null
    private var RAM:Int? = null
    private var screenSize:Double? = null
    private var externalMouse:Boolean? = null
    private var battery:String? = null

    fun setOS(OS:String){
        this.OS = OS
    }
    fun getOS():String?{
        return this.OS
    }
    fun setRAM(RAM:Int){
        this.RAM = RAM
    }
    fun getRAM():Int?{
        return this.RAM
    }
    fun setScreenSize(screenSize:Double){
        this.screenSize = screenSize
    }
    fun getScreenSize():Double?{
        return this.screenSize
    }
    fun setExternalMouse(externalMouse:Boolean){
        this.externalMouse = externalMouse
    }
    fun getExternalMouse():Boolean?{
        return this.externalMouse
    }
    fun setBattery(battery:String){
        this.battery = battery
    }
    fun getBattery():String?{
        return this.battery
    }
}

class Computer{

    var cb:ComputerBuilder
    constructor(compBuild:ComputerBuilder) {
        this.cb = compBuild
    }

    fun build():String{

        return ("The required configuration is :" +
                "\nOS : ${cb.getOS()} " +
                "\nRAM : ${cb.getRAM()} " +
                "\nscreenSize : ${cb.getScreenSize()} " +
                "\nexternalMouse : ${cb.getExternalMouse()} " +
                "\nbattery : ${cb.getBattery()}"
                )
    }
}

fun main(args: Array<String>) {
    var compBuilder = ComputerBuilder()
    compBuilder.setOS("windows")
    compBuilder.setRAM(12)
    compBuilder.setBattery("Inbuilt")
    // not setting any value for external mouse

    var comp = Computer(compBuilder)
    println(comp.build())
}


Output of the Builder Pattern with kotlin


The required configuration is :
OS : windows 
RAM : 12 
screenSize : null 
externalMouse : null 
battery : Inbuilt

Fluent Interface with Builder Pattern in kotlin | Design Patterns

In main function, we have used below code


var compBuilder = ComputerBuilder()
compBuilder.setOS("windows")
compBuilder.setRAM(12)
compBuilder.setBattery("Inbuilt")

But most of the time we would like to have our code like below, we can achieve it by creating the fluent interface


var compBuilder = ComputerBuilder()
compBuilder.setOS("windows").setRAM(12).setBattery("Inbuilt")

Fluent Interface in kotlin :

As per my understanding, fluent interface is nothing but return the same object in the functions rather than different values You can achieve it by chaaning the return type of the set functions like belwo


fun setScreenSize(screenSize:Double):ComputerBuilder{
	this.screenSize = screenSize
	return this
}

Kotlin Builder pattern with Fluent interface


open class ComputerBuilder{
    private var OS:String? = null
    private var RAM:Int? = null
    private var screenSize:Double? = null
    private var externalMouse:Boolean? = null
    private var battery:String? = null

    fun setOS(OS:String):ComputerBuilder{
        this.OS = OS
        return this
    }
    fun getOS():String?{
        return this.OS
    }
    fun setRAM(RAM:Int):ComputerBuilder{
        this.RAM = RAM
        return this
    }
    fun getRAM():Int?{
        return this.RAM
    }
    fun setScreenSize(screenSize:Double):ComputerBuilder{
        this.screenSize = screenSize
        return this
    }
    fun getScreenSize():Double?{
        return this.screenSize
    }
    fun setExternalMouse(externalMouse:Boolean):ComputerBuilder{
        this.externalMouse = externalMouse
        return this
    }
    fun getExternalMouse():Boolean?{
        return this.externalMouse
    }
    fun setBattery(battery:String):ComputerBuilder{
        this.battery = battery
        return this
    }
    fun getBattery():String?{
        return this.battery
    }
}

class Computer{

    var cb:ComputerBuilder
    constructor(compBuild:ComputerBuilder) {
        this.cb = compBuild
    }

    fun build():String{

        return ("The required configuration is :" +
                "\nOS : ${cb.getOS()} " +
                "\nRAM : ${cb.getRAM()} " +
                "\nscreenSize : ${cb.getScreenSize()} " +
                "\nexternalMouse : ${cb.getExternalMouse()} " +
                "\nbattery : ${cb.getBattery()}"
                )
    }
}

fun main(args: Array<String>) {
    var compBuilder = ComputerBuilder()
    compBuilder.setOS("windows").setRAM(12).setBattery("Inbuilt")
    // not setting any value for external mouse

    var comp = Computer(compBuilder)
    println(comp.build())
}

Output of the Kotlin Builder pattern with Fluent interface program


The required configuration is :
OS : windows 
RAM : 12 
screenSize : null 
externalMouse : null 
battery : Inbuilt

 
Join My Facebook Group
Join Group
 
aaaaaaaaaaaaa
Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions

Recent Addition

new tutorial Selenium Online Training : Our next online training course for Selenium with Java starts from 17th December 2018.

You can attend first 3 classes for free, the total course fee is INR 10,000

The course time would be 8.00 PM(IST) for the first three classes

If you are interested to learn, then you can join the course by sending email to chercher.tech@gmail.com

or Register below


 
Join My Facebook Group
Join Group