Design Patterns With Kotlin

Overview

DesignPatterns-Kotlin

Design Patterns

  • In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. A design pattern isn't a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.

Creational design patterns

  • Singleton
  • prototype
  • Object Pool
  • Factory Method
  • Builder
  • Abstract Factory

Structural design patterns

  • Adapter
  • Bridge
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Private Class Data
  • Proxy

Behavioral design patterns

  • Chain of responsibility
  • Command
  • Interpreter
  • Iterator
  • Mediator
  • Memento
  • Null Object
  • Observer
  • State
  • Strategy
  • Template method
  • Visitor

Creational design patterns

  • Singleton

The singleton pattern ensures that only one object of a particular class is ever created. All further references to objects of the singleton class refer to the same underlying instance. There are very few applications, do not overuse this pattern!

UML :

Example:

class Counter private constructor() {
    var count = 0
    fun addOne() {
        count++
    }

    companion object {
        val instance = Counter()
    }
}

Usage :

    val obj1: Counter = Counter.instance
    val obj2: Counter = Counter.instance
    obj1.addOne()
    obj2.addOne()
    println("Counter 1 : ${obj1.count}")
    println("Counter 2 : ${obj2.count}")

    obj1.addOne()
    obj2.addOne()
    println("Counter 1 : ${obj1.count}")
    println("Counter 2 : ${obj2.count}")

Output :

Counter 1 : 2
Counter 2 : 2
Counter 1 : 4
Counter 2 : 4

prototype

The Prototype pattern delegates the cloning process to the actual objects that are being cloned. The patte![prototype] rn declares a common interface for all objects that support cloning. This interface lets you clone an object without coupling your code to the class of that object. Usually, such an interface contains just a single clone method.

The implementation of the clone method is very similar in all classes. The method creates an object of the current class and carries over all of the field values of the old object into the new one. You can even copy private fields because most programming languages let objects access private fields of other objects that belong to the same class.

An object that supports cloning is called a prototype. When your objects have dozens of fields and hundreds of possible configurations, cloning them might serve as an alternative to subclassing.

UML :

Example:

import java.util.ArrayList

class WordDocument 
constructor(var text: String = "", private var images: ArrayList<String> = ArrayList<String>()) : Cloneable {


    init {
        println("-----Init-----")
    }

    fun addImage(image: String) = images.add(image)

    fun showDocument() {
        println("-----Start-----")
        println("Text: $text")
        println("Images List: ")
        images.map {
            println("Image name: $it")
        }
        println("-----End-----")
    }

    fun cloneTo(): WordDocument? {
        try {
            val copy: WordDocument = super.clone() as WordDocument
            copy.text = this.text
            copy.images = this.images.clone() as ArrayList<String>
            return copy
        } catch (e: CloneNotSupportedException) {
            e.printStackTrace()
        }
        return null
    }

}

Usage :

fun main() {
    val originDoc: WordDocument = WordDocument().apply {
        text = "This is a document"
        addImage("Image 1")
        addImage("Image 2")
        addImage("Image 3")
        showDocument()


    }

    val copyDoc: WordDocument? = originDoc.cloneTo()?.apply {
        showDocument()
        text = "This is a copy document"
        addImage("A new image")
        showDocument()
    }
    copyDoc!!.showDocument()
}

Output:

-----Init-----
-----Start-----
Text: This is a document
Images List: 
Image name: Image 1
Image name: Image 2
Image name: Image 3
-----End-----
-----Start-----
Text: This is a document
Images List: 
Image name: Image 1
Image name: Image 2
Image name: Image 3
-----End-----
-----Start-----
Text: This is a copy document
Images List: 
Image name: Image 1
Image name: Image 2
Image name: Image 3
Image name: A new image
-----End-----
-----Start-----
Text: This is a copy document
Images List: 
Image name: Image 1
Image name: Image 2
Image name: Image 3
Image name: A new image
-----End-----

Builder

The builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm. An external class controls the construction algorithm.

UML :

Example:

data class Car
constructor(var color: String, var licensePlate: String, var brand: String) {

    private constructor(builder: Builder) : this(
        builder.color,
        builder.licensePlate,
        builder.brand
    )

    class Builder {
        lateinit var color: String
        lateinit var licensePlate: String
        lateinit var brand: String

        fun color(init: Builder.() -> String) = apply { color = init() }
        fun licensePlate(init: Builder.() -> String) = apply { licensePlate = init() }
        fun brand(init: Builder.() -> String) = apply { brand = init() }
    }

    companion object {
        fun build(init: Builder.() -> Unit) = Car(Builder().apply(init))
    }

}

Usage:

    val car1 = Car.build {
        brand = "Audi"
        color = "Blue"
        licensePlate = "C88888"
    }
    println(car1)

Output:

Car(color=Blue, licensePlate=C88888, brand=Audi)

Factory Method

The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time.

UML :

Example:

interface Cake {
    fun prepareMaterials();
    fun banking();
}
class MangoCake : Cake {
    override fun prepareMaterials() {
        println("prepare Mango Cream")
    }

    override fun banking() {
        println("Baking ten minutes")
    }
}
abstract class Factory {
    abstract fun <T : Cake> createProduct(clz:Class<T>): T?
}
class CakeFactory : Factory() {
    override fun <T : Cake> createProduct(clz: Class<T>): T? {
        var cake: Cake? = null
        try {
            cake = Class.forName(clz.name).getDeclaredConstructor().newInstance() as Cake
        }catch (e : Exception) {
            e.printStackTrace()
        }
        return cake as T?
    }
}

Usage :

    val factory : Factory = CakeFactory()
    val mangoCake = factory.createProduct(MangoCake::class.java)?.apply {
        prepareMaterials()
        banking()
    }

Outpu:

prepare Mango Cream
Baking ten minutes

Abstract Factory

The abstract factory pattern is used to provide a client with a set of related or dependant objects. The "family" of objects created by the factory are determined at run-time.

UML :

Example:

abstract class CakeFactory {
    abstract fun cream():CakeCream
    abstract fun style():CakeStyle
}
abstract class CakeCream {
    abstract fun cream()
}
abstract class CakeStyle {
    abstract fun style()
}
class HeartStyle:CakeStyle() {
    override fun style() {
        println("Heart Style")
    }
}
class MangoCream:CakeCream() {
    override fun cream() {
        println("Mango Cream")
    }
}
class MangoHeartCake : CakeFactory(){
    override fun cream(): CakeCream {
        return MangoCream()
    }

    override fun style(): CakeStyle {
        return HeartStyle()
    }
}

Usage :

    val mangoHeartCake: CakeFactory = MangoHeartCake()
    mangoHeartCake.cream().cream()
    mangoHeartCake.style().style()

    println("=================")

    val mangoSquareCake: CakeFactory = MangoSquareCake()
    mangoSquareCake.cream().cream()
    mangoSquareCake.style().style()

Outpu:

Mango Cream
Heart Style
=================
Mango Cream
Square Style

Structural Patterns :

Protection Proxy

The proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object. Protection proxy is restricting access.

UML :

Example:

interface IPicker {
    fun receiveMessage()
    fun takeCourier()
    fun signatureAcceptance()
}
class RealPicker:IPicker {
    override fun receiveMessage() {
        println("Receive text Message")
    }

    override fun takeCourier() {
        println("Take the Courier")
    }

    override fun signatureAcceptance() {
        println("Signature Acceptance")
    }
}
class ProxyPicker(private val picker: IPicker) : IPicker by picker

Usage :

    val picker:IPicker  = RealPicker()
    val proxyPicker = ProxyPicker(picker)
    proxyPicker.receiveMessage()
    proxyPicker.takeCourier()
    proxyPicker.signatureAcceptance()

Outpu:

Receive text Message
Take the Courier
Signature Acceptance

Decorator

The decorator pattern is used to extend or alter the functionality of objects at run-time by wrapping them in an object of a decorator class. This provides a flexible alternative to using inheritance to modify behaviour.

UML :

Example:

interface Cake {
    fun make()
}
class CakeEmbryo : Cake {
    override fun make() {
        println("Baking Cake")
    }
}
open class DecoratorCake constructor(val cake : Cake): Cake by cake
class FruitCake constructor(cake:Cake) :DecoratorCake(cake) {

    override fun make() {
        addSomeFruit()
        super.make()
    }

    private fun addSomeFruit() {
        println("Add Some Fruit")
    }

}

Usage :

    val cake: Cake = CakeEmbryo()
    cake.make()

    println("--------Decorate Fruit Cake--------")
    val fruitCake: DecoratorCake = FruitCake(cake)
    fruitCake.make()

Outpu:

Baking Cake
--------Decorate Fruit Cake--------
Add Some fruit
Baking Cake

Adapter

The adapter pattern is used to provide a link between two otherwise incompatible types by wrapping the "adaptee" with a class that supports the interface required by the client.

UML :

Example:

interface VoltFive {
    fun provideVoltFive():Int
}
class Volt220 {

    fun provideVolt220(): Int {
        return 220
    }
}
class VoltAdapter(private val volt220: Volt220) : VoltFive {

    override fun provideVoltFive(): Int {
        val volt = volt220.provideVolt220()
        return 5
    }

    fun provideVolt220(): Int {
        return volt220.provideVolt220()
    }
}

Usage :

    val volt220 = Volt220()
    val adapter = VoltAdapter(volt220)

    val volt = adapter.provideVoltFive()
    println("After adapter, the volt is : $volt")

Outpu:

After adapter, the volt is :5

Facade

The facade pattern is used to define a simplified interface to a more complex subsystem.

UML :

Example:

interface Italykitchen {

    fun lasagneWithTomatoAndCheese()
    fun prawnRisotto()
    fun creamCaramel()
}
class ItalykitchenImpl : Italykitchen {
    override fun lasagneWithTomatoAndCheese() {
        println("Lasagne With Tomato And Cheese")
    }

    override fun prawnRisotto() {
        println("Prawn Risotto")
    }

    override fun creamCaramel() {
        println("Cream Caramel")
    }
}
interface Frenchkitchen {

    fun bouillabaisse()
    fun cassoulet()
    fun pouleAuPot()

}
class FrenchkitchenImpl : Frenchkitchen {
    override fun bouillabaisse() {
        println("Bouillabaisse")
    }

    override fun cassoulet() {
        println("Cassoulet")
    }

    override fun pouleAuPot() {
        println("PouleAuPot")
    }
}
class Menu {
    private val italykitchen: Italykitchen
    private val frenchkitchen: Frenchkitchen

    init {
        italykitchen = ItalykitchenImpl()
        frenchkitchen = FrenchkitchenImpl()
    }

    fun bouillabaisse() {
        frenchkitchen.bouillabaisse()
    }

    fun cassoulet() {
        frenchkitchen.cassoulet()
    }

    fun pouleAuPot() {
        frenchkitchen.pouleAuPot()
    }

    fun lasagneWithTomatoAndCheese() {
        italykitchen.lasagneWithTomatoAndCheese()
    }

    fun prawnRisotto() {
        italykitchen.prawnRisotto()
    }

    fun creamCaramel() {
        italykitchen.creamCaramel()
    }

}

Usage :

    val menu = Menu()
    println("Customer order")
    menu.lasagneWithTomatoAndCheese()
    menu.creamCaramel()

    println("===========New Order==========")
    println("Customer two orders")
    menu.bouillabaisse()
    menu.prawnRisotto()

Outpu:

Customer order
Lasagne With Tomato And Cheese
Cream Caramel
===========New Order==========
Customer two orders
Bouillabaisse
Prawn Risotto
You might also like...
A simple demo project based on MVVM clean architecture and material design & animations.
A simple demo project based on MVVM clean architecture and material design & animations.

GithubFollows A simple demo project based on MVVM clean architecture and material design & animations. Architecture Specs & Open-source libraries Mini

New style for app design Online Sunglasses Shop App UI made in Jetpack Compose.😉😎
New style for app design Online Sunglasses Shop App UI made in Jetpack Compose.😉😎

JetSunglassUI-Android New style for app design Online Sunglasses Shop App UI made in Jetpack Compose. 😉 😎 (Navigation Components, Dagger-Hilt, Mater

Sushi Design System - UI Kit for Android apps
Sushi Design System - UI Kit for Android apps

Sushi Design System ⚡️ Android UI Kit ⚡️ Application is available here: Latest release: Usage The master branch is being used for release and dev is t

 🗡️ Deddit demonstrates modern Android development with Hilt, Coroutines, Flow, Jetpack, and Material Design based on MVVM architecture
🗡️ Deddit demonstrates modern Android development with Hilt, Coroutines, Flow, Jetpack, and Material Design based on MVVM architecture

Deddit demonstrates modern Android development with Hilt, Coroutines, Flow, Jetpack (ViewModel,Paging3), and Material Design based on MVVM

Quiz Zone is a simple ✅ Quiz Android application 📱 using Firbase Firestore Database and Material Design.
Quiz Zone is a simple ✅ Quiz Android application 📱 using Firbase Firestore Database and Material Design.

Quiz Zone Quiz Zone is a simple ✅ Quiz Android application 📱 using Firbase Firestore Database and Material Design. You can Install and test Quiz Zone

A movie & TV show exploration app that implements MVVM design pattern by following the clean architecture principles, using TMDB API.
A movie & TV show exploration app that implements MVVM design pattern by following the clean architecture principles, using TMDB API.

🎬 Movie App 📺 A movie & TV show exploration app that implements MVVM design pattern by following the clean architecture principles, using TMDB API.

Android implementation of the Flamingo Design System
Android implementation of the Flamingo Design System

It is an Android implementation of the Flamingo Design System. It Consists Of: Palette, theme colors, typography, icon set, illustrations, gradients a

A tool to model and analyze the design of systems from .class files
A tool to model and analyze the design of systems from .class files

sift A tool to model and analyze the design of systems from java class files. Features CLI tool for building, querying and diff-ing "system models" fr

Repo: Programming problems with solutions in Kotlin to help avid Kotlin learners to get a strong hold on Kotlin programming.

Kotlin_practice_problems Repo: Programming problems with solutions in Kotlin to help avid Kotlin learners to get a strong hold on Kotlin programming.

Owner
mohamed tamer
Android Developer Kotlin & Java
mohamed tamer
Kotlin Example of how to organize your code using MVC and some patterns seen in class

Kotlin Example of how to organize your code using MVC and some patterns seen in class

José Luis González Sánchez 3 Mar 23, 2022
A project to learn about Reactive Microservices experimenting with architectures and patterns

reactive-microservices-workshop Copyright © 2021 Aleix Morgadas - Licenced under CC BY-SA 4.0 A project to learn about Reactive Microservices experime

Aleix Morgadas 7 Feb 21, 2022
This project explores the saga architecture for two patterns. The Choreograhy and the Orchestration

Newscast Explorer Technologies used Introduction In this project are going to explore a known EIP known as Saga. A saga is in its essence, a way to de

João Filipe Sabino Esperancinha 2 Dec 15, 2022
TheMovies 🎬 A demo project for The Movie DB based on Kotlin MVVM architecture and material design & animations.

A simple project for The Movie DB based on Kotlin MVVM clean architecture and material design & animations. How to build on your environment

Jaewoong Eum 420 Nov 29, 2022
Spring Boot Example with Kotlin and Domain Driven Design

Spring Boot Kotlin Domain Driven Design Example Just an example project where ddd is implemented with some other great patterns and architecture from

Fernando Guevara Sanchez 16 Jun 29, 2022
AbstractFactoryDesignPatternWithKotlin - Abstract Factory Design Pattern With Kotlin

AbstractFactoryDesignPatternWithKotlin Abstract Factory Design Pattern With Kotl

Harun Kör 2 Jun 16, 2022
AbstractFactoryDesignPatternWithKotlin - Abstract Factory Design Pattern With Kotlin

AbstractFactoryDesignPatternWithKotlin Abstract Factory Design Pattern With Kotl

Harun Kör 1 Jan 2, 2022
DesignLogin-Register - Design Login and Register With Kotlin

Diseños de Login en XML En esta ocasión vengo a presentar diseños de inicio de s

Paul Guillen Acuña 0 Apr 21, 2022
Kotlin extension function provides a facility to "add" methods to class without inheriting a class or using any type of design pattern

What is Kotlin Extension Function ? Kotlin extension function provides a facility to "add" methods to class without inheriting a class or using any ty

mohsen 21 Dec 3, 2022
Demonstration of Object Pool Design Pattern using Kotlin language and Coroutine

Object Pool Design Pattern with Kotlin Demonstration of Thread Safe Object Pool Design Pattern using Kotlin language and Coroutine. Abstract The objec

Enes Kayıklık 7 Apr 12, 2022