Creational Design Patterns with Kotlin

Ecem Okan
4 min readDec 13, 2022

--

Design patterns

In software design, they are patterns created to solve common problems that are frequently encountered in problems. Design patterns are also concerned with the flexibility and reusability of solutions implemented in the software process.

Each pattern describes a problem that recurs in our environment and then describes the application of the solution to that problem in such a way that you can use that solution a million times without doing it the same way twice.

Creational Design Patterns

In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.

In this topic, we are going to talk about five design patterns. But you should know that there are another creational design patterns too such as Object Pool etc.

1. Factory Patterns

Factory Design Pattern is a structure that provides background generation of a class or object. It provides an interface to create related objects and allows subclasses to instantiate which class.

In this pattern, the client can know which class instance it can take, but not the creation details. In other words, how the object will be created, are abstracted.

Audi Output: brand='A4', modal='Black'
Bmw Output: brand='118i', modal='White'

2. Abstract Factory Patterns

Abstract Factory is used to establish product groups that are related to each other. To be more specific, it provides an interface to create interrelated product families.

The difference from Factory pattern is that it creates a group. It can be thought of as a factory producing factory.

3. Singleton Patterns

A class must have only one instance, and that instance must be provided with a global access point. With this pattern, we prevent the object from being recreated.

The static keyword is important for this design pattern. We cannot create a singleton without a static key. Because you remember that static is always created once in memory. Also, constructor must be private.

The singleton members are prepared before the program is up and never die within the application. They are not destroyed by the garbage collector by leaving the class. For this reason, not everything should be made a singleton. Singletons can be used for objects that are used regularly in the application.

In right below you can see that init has been called only once even if we called PrenterObject.printObject() twice.

Start
Call init: com.ecemokan.creationaldesignpattern.singleton.PrenterObject@3ac3fd8b
Printing with object: com.ecemokan.creationaldesignpattern.singleton.PrenterObject@3ac3fd8b
Printing with object: com.ecemokan.creationaldesignpattern.singleton.PrenterObject@3ac3fd8b

4. Builder

Builder is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.

The builder pattern is a pattern used in the creation of complex objects, so that the client can produce by specifying only the object type. The Builder pattern is used to completely hide the creation of a complex object consisting of multiple parts and the creation phases of this complex object from the client module. This pattern is used when there is more than one presentation of the actual product that the client wants to use.

Address(phone=0 (555) 555 55 55, title=New Address, no=17A, city=NewYork)

What does “.()” mean in Kotlin?

A function that takes in nothing and returns nothing in Kotlin looks like:

var function : () -> Unit

The difference is that the function in your code takes in nothing, returns nothing, but is invoked on an object.

For example,

class Builder (val multiplier: Int) {

fun invokeStuff(action: (Builder.() -> Unit)) {
this.action()
}

fun multiply(value: Int) : Int {
return value * multiplier
}
}

The important bit here is the way we’ve declared the type of action

action: (Builder.() -> Unit)

This is a function that returns nothing, takes in nothing but is invoked on an object of type Builder.

This means when we use this builder like so

var builder = Builder(10)
builder.invokeStuff({
var result = multiply(1)
println(result)
})

The context of this has been set to the builder object and we can invoke functions declared within the builder.

5. Prototype

The prototype design pattern enables the creation of prototypes of existing objects. The main reason for designing the prototype pattern is to quickly produce another object of the same type over the related object.

----- Origin Address -----
City : NewYork
No : 17A
Title : Origin Address
Phone: 0 (555) 555 55 55
----- Copy Address -----
City : Copy NewYork
No : 17A
Title : Copy Address
Phone: 0 (555) 555 55 55

Design pattern is the ideal step for solving a problem. If the effect is to be created throughout the programming, the design pattern is applied. However, the Design pattern also has an anti-pattern. We should know in which cases the design pattern should be used and in which cases we do not need it.

In my next articles, I will be talking about Behavioral and Structural design patterns.

If you are interested in Swift, I recommend you to read Creational Design Patterns with Swift by Pınar Koçak.

--

--