{"id":13392874,"url":"https://github.com/dbacinski/Design-Patterns-In-Kotlin","last_synced_at":"2025-03-13T19:31:07.757Z","repository":{"id":37612103,"uuid":"69291380","full_name":"dbacinski/Design-Patterns-In-Kotlin","owner":"dbacinski","description":"Design Patterns implemented in Kotlin","archived":false,"fork":false,"pushed_at":"2024-06-11T06:11:21.000Z","size":269,"stargazers_count":5945,"open_issues_count":5,"forks_count":699,"subscribers_count":195,"default_branch":"master","last_synced_at":"2025-03-11T22:13:29.764Z","etag":null,"topics":["design","design-patterns","kotlin","kotlin-android"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dbacinski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-26T20:47:03.000Z","updated_at":"2025-03-10T08:41:00.000Z","dependencies_parsed_at":"2024-01-06T02:02:25.451Z","dependency_job_id":"3c02eb81-b138-4ab0-9477-8f6bdd18e8ea","html_url":"https://github.com/dbacinski/Design-Patterns-In-Kotlin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbacinski%2FDesign-Patterns-In-Kotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbacinski%2FDesign-Patterns-In-Kotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbacinski%2FDesign-Patterns-In-Kotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbacinski%2FDesign-Patterns-In-Kotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dbacinski","download_url":"https://codeload.github.com/dbacinski/Design-Patterns-In-Kotlin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243469122,"owners_count":20295691,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["design","design-patterns","kotlin","kotlin-android"],"created_at":"2024-07-30T17:00:38.520Z","updated_at":"2025-03-13T19:31:07.731Z","avatar_url":"https://github.com/dbacinski.png","language":"Kotlin","readme":"# Design Patterns In Kotlin\n\n#### :warning: New article about testing: [Unit Testing with Mockito 2](https://github.com/dbacinski/Android-Testing-With-Kotlin/blob/master/docs/Unit-Testing-Mockito.md)\n\nProject maintained by [@dbacinski](http://twitter.com/dbacinski) (Dariusz Baciński)\n\nInspired by [Design-Patterns-In-Swift](https://github.com/ochococo/Design-Patterns-In-Swift) by [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki)\n\n## Table of Contents\n\n* [Behavioral Patterns](#behavioral)\n\t* [Observer / Listener](#observer--listener)\n\t* [Strategy](#strategy)\n\t* [Command](#command)\n\t* [State](#state)\n\t* [Chain of Responsibility](#chain-of-responsibility)\n\t* [Visitor](#visitor)\n\t* [Mediator](#mediator)\n\t* [Memento](#memento)\n* [Creational Patterns](#creational)\n\t* [Builder / Assembler](#builder--assembler)\n\t* [Factory Method](#factory-method)\n\t* [Singleton](#singleton)\n\t* [Abstract Factory](#abstract-factory)\n* [Structural Patterns](#structural)\n\t* [Adapter](#adapter)\n\t* [Decorator](#decorator)\n\t* [Facade](#facade)\n\t* [Protection Proxy](#protection-proxy)\n\t* [Composite](#composite)\n\nBehavioral\n==========\n\n\u003eIn software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.\n\u003e\n\u003e**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Behavioral_pattern)\n\n[Observer / Listener](/patterns/src/test/kotlin/Listener.kt)\n--------\n\nThe observer pattern is used to allow an object to publish changes to its state.\nOther objects subscribe to be immediately notified of any changes.\n\n#### Example\n\n```kotlin\ninterface TextChangedListener {\n\n    fun onTextChanged(oldText: String, newText: String)\n}\n\nclass PrintingTextChangedListener : TextChangedListener {\n    \n    private var text = \"\"\n    \n    override fun onTextChanged(oldText: String, newText: String) {\n        text = \"Text is changed: $oldText -\u003e $newText\"\n    }\n}\n\nclass TextView {\n\n    val listeners = mutableListOf\u003cTextChangedListener\u003e()\n\n    var text: String by Delegates.observable(\"\u003cempty\u003e\") { _, old, new -\u003e\n        listeners.forEach { it.onTextChanged(old, new) }\n    }\n}\n```\n\n#### Usage\n\n```kotlin\nval textView = TextView().apply {\n    listeners.add(PrintingTextChangedListener())\n}\n\nwith(textView) {\n    text = \"Lorem ipsum\"\n    text = \"dolor sit amet\"\n}\n```\n\n#### Output\n\n```\nText is changed \u003cempty\u003e -\u003e Lorem ipsum\nText is changed Lorem ipsum -\u003e dolor sit amet\n```\n\n[Strategy](/patterns/src/test/kotlin/Strategy.kt)\n-----------\n\nThe strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time.\n\n#### Example\n\n```kotlin\nclass Printer(private val stringFormatterStrategy: (String) -\u003e String) {\n\n    fun printString(string: String) {\n        println(stringFormatterStrategy(string))\n    }\n}\n\nval lowerCaseFormatter: (String) -\u003e String = { it.toLowerCase() }\nval upperCaseFormatter = { it: String -\u003e it.toUpperCase() }\n```\n\n#### Usage\n\n```kotlin\nval inputString = \"LOREM ipsum DOLOR sit amet\"\n\nval lowerCasePrinter = Printer(lowerCaseFormatter)\nlowerCasePrinter.printString(inputString)\n\nval upperCasePrinter = Printer(upperCaseFormatter)\nupperCasePrinter.printString(inputString)\n\nval prefixPrinter = Printer { \"Prefix: $it\" }\nprefixPrinter.printString(inputString)\n```\n\n#### Output\n\n```\nlorem ipsum dolor sit amet\nLOREM IPSUM DOLOR SIT AMET\nPrefix: LOREM ipsum DOLOR sit amet\n```\n\n[Command](/patterns/src/test/kotlin/Command.kt)\n-------\n\nThe command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use.\n\n#### Example:\n\n```kotlin\ninterface OrderCommand {\n    fun execute()\n}\n\nclass OrderAddCommand(val id: Long) : OrderCommand {\n    override fun execute() = println(\"Adding order with id: $id\")\n}\n\nclass OrderPayCommand(val id: Long) : OrderCommand {\n    override fun execute() = println(\"Paying for order with id: $id\")\n}\n\nclass CommandProcessor {\n\n    private val queue = ArrayList\u003cOrderCommand\u003e()\n\n    fun addToQueue(orderCommand: OrderCommand): CommandProcessor =\n        apply {\n            queue.add(orderCommand)\n        }\n\n    fun processCommands(): CommandProcessor =\n        apply {\n            queue.forEach { it.execute() }\n            queue.clear()\n        }\n}\n```\n\n#### Usage\n\n```kotlin\nCommandProcessor()\n    .addToQueue(OrderAddCommand(1L))\n    .addToQueue(OrderAddCommand(2L))\n    .addToQueue(OrderPayCommand(2L))\n    .addToQueue(OrderPayCommand(1L))\n    .processCommands()\n```\n\n#### Output\n\n```\nAdding order with id: 1\nAdding order with id: 2\nPaying for order with id: 2\nPaying for order with id: 1\n```\n\n[State](/patterns/src/test/kotlin/State.kt)\n------\n\nThe state pattern is used to alter the behaviour of an object as its internal state changes.\nThe pattern allows the class for an object to apparently change at run-time.\n\n#### Example\n\n```kotlin\nsealed class AuthorizationState\n\nobject Unauthorized : AuthorizationState()\n\nclass Authorized(val userName: String) : AuthorizationState()\n\nclass AuthorizationPresenter {\n\n    private var state: AuthorizationState = Unauthorized\n\n    val isAuthorized: Boolean\n        get() = when (state) {\n            is Authorized -\u003e true\n            is Unauthorized -\u003e false\n        }\n\n    val userName: String\n        get() {\n            val state = this.state //val enables smart casting of state\n            return when (state) {\n                is Authorized -\u003e state.userName\n                is Unauthorized -\u003e \"Unknown\"\n            }\n        }\n\n    fun loginUser(userName: String) {\n        state = Authorized(userName)\n    }\n\n    fun logoutUser() {\n        state = Unauthorized\n    }\n\n    override fun toString() = \"User '$userName' is logged in: $isAuthorized\"\n}\n```\n\n#### Usage\n\n```kotlin\nval authorizationPresenter = AuthorizationPresenter()\n\nauthorizationPresenter.loginUser(\"admin\")\nprintln(authorizationPresenter)\n\nauthorizationPresenter.logoutUser()\nprintln(authorizationPresenter)\n```\n\n#### Output\n\n```\nUser 'admin' is logged in: true\nUser 'Unknown' is logged in: false\n```\n\n[Chain of Responsibility](/patterns/src/test/kotlin/ChainOfResponsibility.kt)\n-----------------------\n\nThe chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler.\n\n#### Example\n\n```kotlin\ninterface HeadersChain {\n    fun addHeader(inputHeader: String): String\n}\n\nclass AuthenticationHeader(val token: String?, var next: HeadersChain? = null) : HeadersChain {\n\n    override fun addHeader(inputHeader: String): String {\n        token ?: throw IllegalStateException(\"Token should be not null\")\n        return inputHeader + \"Authorization: Bearer $token\\n\"\n            .let { next?.addHeader(it) ?: it }\n    }\n}\n\nclass ContentTypeHeader(val contentType: String, var next: HeadersChain? = null) : HeadersChain {\n\n    override fun addHeader(inputHeader: String): String =\n        inputHeader + \"ContentType: $contentType\\n\"\n            .let { next?.addHeader(it) ?: it }\n}\n\nclass BodyPayload(val body: String, var next: HeadersChain? = null) : HeadersChain {\n\n    override fun addHeader(inputHeader: String): String =\n        inputHeader + body.let { next?.addHeader(it) ?: it }\n}\n```\n\n#### Usage\n\n```kotlin\n//create chain elements\nval authenticationHeader = AuthenticationHeader(\"123456\")\nval contentTypeHeader = ContentTypeHeader(\"json\")\nval messageBody = BodyPayload(\"Body:\\n{\\n\\\"username\\\"=\\\"dbacinski\\\"\\n}\")\n\n//construct chain\nauthenticationHeader.next = contentTypeHeader\ncontentTypeHeader.next = messageBody\n\n//execute chain\nval messageWithAuthentication =\n    authenticationHeader.addHeader(\"Headers with Authentication:\\n\")\nprintln(messageWithAuthentication)\n\nval messageWithoutAuth =\n    contentTypeHeader.addHeader(\"Headers:\\n\")\nprintln(messageWithoutAuth)\n```\n\n#### Output\n\n```\nHeaders with Authentication:\nAuthorization: Bearer 123456\nContentType: json\nBody:\n{\n\"username\"=\"dbacinski\"\n}\n\nHeaders:\nContentType: json\nBody:\n{\n\"username\"=\"dbacinski\"\n}\n```\n\n[Visitor](/patterns/src/test/kotlin/Visitor.kt)\n-------\n\nThe visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold.\n\n#### Example\n\n```kotlin\ninterface ReportVisitable {\n    fun \u003cR\u003e accept(visitor: ReportVisitor\u003cR\u003e): R\n}\n\nclass FixedPriceContract(val costPerYear: Long) : ReportVisitable {\n    override fun \u003cR\u003e accept(visitor: ReportVisitor\u003cR\u003e): R = visitor.visit(this)\n}\n\nclass TimeAndMaterialsContract(val costPerHour: Long, val hours: Long) : ReportVisitable {\n    override fun \u003cR\u003e accept(visitor: ReportVisitor\u003cR\u003e): R = visitor.visit(this)\n}\n\nclass SupportContract(val costPerMonth: Long) : ReportVisitable {\n    override fun \u003cR\u003e accept(visitor: ReportVisitor\u003cR\u003e): R = visitor.visit(this)\n}\n\ninterface ReportVisitor\u003cout R\u003e {\n\n    fun visit(contract: FixedPriceContract): R\n    fun visit(contract: TimeAndMaterialsContract): R\n    fun visit(contract: SupportContract): R\n}\n\nclass MonthlyCostReportVisitor : ReportVisitor\u003cLong\u003e {\n\n    override fun visit(contract: FixedPriceContract): Long =\n        contract.costPerYear / 12\n\n    override fun visit(contract: TimeAndMaterialsContract): Long =\n        contract.costPerHour * contract.hours\n\n    override fun visit(contract: SupportContract): Long =\n        contract.costPerMonth\n}\n\nclass YearlyReportVisitor : ReportVisitor\u003cLong\u003e {\n\n    override fun visit(contract: FixedPriceContract): Long =\n        contract.costPerYear\n\n    override fun visit(contract: TimeAndMaterialsContract): Long =\n        contract.costPerHour * contract.hours\n\n    override fun visit(contract: SupportContract): Long =\n        contract.costPerMonth * 12\n}\n```\n\n#### Usage\n\n```kotlin\nval projectAlpha = FixedPriceContract(costPerYear = 10000)\nval projectGamma = TimeAndMaterialsContract(hours = 150, costPerHour = 10)\nval projectBeta = SupportContract(costPerMonth = 500)\nval projectKappa = TimeAndMaterialsContract(hours = 50, costPerHour = 50)\n\nval projects = arrayOf(projectAlpha, projectBeta, projectGamma, projectKappa)\n\nval monthlyCostReportVisitor = MonthlyCostReportVisitor()\n\nval monthlyCost = projects.map { it.accept(monthlyCostReportVisitor) }.sum()\nprintln(\"Monthly cost: $monthlyCost\")\nassertThat(monthlyCost).isEqualTo(5333)\n\nval yearlyReportVisitor = YearlyReportVisitor()\nval yearlyCost = projects.map { it.accept(yearlyReportVisitor) }.sum()\nprintln(\"Yearly cost: $yearlyCost\")\nassertThat(yearlyCost).isEqualTo(20000)\n```\n\n#### Output\n\n```\nMonthly cost: 5333\nYearly cost: 20000\n```\n\n[Mediator](/patterns/src/test/kotlin/Mediator.kt)\n-------\n\nMediator design pattern is used to provide a centralized communication medium between different objects in a system. This pattern is very helpful in an enterprise application where multiple objects are interacting with each other.\n#### Example\n\n```kotlin\nclass ChatUser(private val mediator: ChatMediator, val name: String) {\n    fun send(msg: String) {\n        println(\"$name: Sending Message= $msg\")\n        mediator.sendMessage(msg, this)\n    }\n\n    fun receive(msg: String) {\n        println(\"$name: Message received: $msg\")\n    }\n}\n\nclass ChatMediator {\n\n    private val users: MutableList\u003cChatUser\u003e = ArrayList()\n\n    fun sendMessage(msg: String, user: ChatUser) {\n        users\n            .filter { it != user }\n            .forEach {\n                it.receive(msg)\n            }\n    }\n\n    fun addUser(user: ChatUser): ChatMediator =\n        apply { users.add(user) }\n\n}\n```\n\n#### Usage\n\n```kotlin\nval mediator = ChatMediator()\nval john = ChatUser(mediator, \"John\")\n\nmediator\n    .addUser(ChatUser(mediator, \"Alice\"))\n    .addUser(ChatUser(mediator, \"Bob\"))\n    .addUser(john)\njohn.send(\"Hi everyone!\")\n```\n\n#### Output\n\n```\nJohn: Sending Message= Hi everyone!\nAlice: Message received: Hi everyone!\nBob: Message received: Hi everyone!\n```\n\n[Memento](/patterns/src/test/kotlin/Memento.kt)\n-------\n\nThe memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback).\n\n#### Example\n```kotlin\ndata class Memento(val state: String)\n\nclass Originator(var state: String) {\n\n    fun createMemento(): Memento {\n        return Memento(state)\n    }\n\n    fun restore(memento: Memento) {\n        state = memento.state\n    }\n}\n\nclass CareTaker {\n    private val mementoList = ArrayList\u003cMemento\u003e()\n\n    fun saveState(state: Memento) {\n        mementoList.add(state)\n    }\n\n    fun restore(index: Int): Memento {\n        return mementoList[index]\n    }\n}\n```\n\n#### Usage\n```kotlin\nval originator = Originator(\"initial state\")\nval careTaker = CareTaker()\ncareTaker.saveState(originator.createMemento())\n\noriginator.state = \"State #1\"\noriginator.state = \"State #2\"\ncareTaker.saveState(originator.createMemento())\n\noriginator.state = \"State #3\"\nprintln(\"Current State: \" + originator.state)\nassertThat(originator.state).isEqualTo(\"State #3\")\n\noriginator.restore(careTaker.restore(1))\nprintln(\"Second saved state: \" + originator.state)\nassertThat(originator.state).isEqualTo(\"State #2\")\n\noriginator.restore(careTaker.restore(0))\nprintln(\"First saved state: \" + originator.state)\n```\n\n#### Output\n```\nCurrent State: State #3\nSecond saved state: State #2\nFirst saved state: initial state\n```\n\nCreational\n==========\n\n\u003e 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.\n\u003e\n\u003e**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Creational_pattern)\n\n[Builder / Assembler](/patterns/src/test/kotlin/Builder.kt)\n----------\n\nThe builder pattern is used to create complex objects with constituent parts that must be created in the same order or using a specific algorithm.\nAn external class controls the construction algorithm.\n\n#### Example\n\n```kotlin\n// Let's assume that Dialog class is provided by external library.\n// We have only access to Dialog public interface which cannot be changed.\n\nclass Dialog {\n\n    fun showTitle() = println(\"showing title\")\n\n    fun setTitle(text: String) = println(\"setting title text $text\")\n\n    fun setTitleColor(color: String) = println(\"setting title color $color\")\n\n    fun showMessage() = println(\"showing message\")\n\n    fun setMessage(text: String) = println(\"setting message $text\")\n\n    fun setMessageColor(color: String) = println(\"setting message color $color\")\n\n    fun showImage(bitmapBytes: ByteArray) = println(\"showing image with size ${bitmapBytes.size}\")\n\n    fun show() = println(\"showing dialog $this\")\n}\n\n//Builder:\nclass DialogBuilder() {\n    constructor(init: DialogBuilder.() -\u003e Unit) : this() {\n        init()\n    }\n\n    private var titleHolder: TextView? = null\n    private var messageHolder: TextView? = null\n    private var imageHolder: File? = null\n\n    fun title(init: TextView.() -\u003e Unit) {\n        titleHolder = TextView().apply { init() }\n    }\n\n    fun message(init: TextView.() -\u003e Unit) {\n        messageHolder = TextView().apply { init() }\n    }\n\n    fun image(init: () -\u003e File) {\n        imageHolder = init()\n    }\n\n    fun build(): Dialog {\n        val dialog = Dialog()\n\n        titleHolder?.apply {\n            dialog.setTitle(text)\n            dialog.setTitleColor(color)\n            dialog.showTitle()\n        }\n\n        messageHolder?.apply {\n            dialog.setMessage(text)\n            dialog.setMessageColor(color)\n            dialog.showMessage()\n        }\n\n        imageHolder?.apply {\n            dialog.showImage(readBytes())\n        }\n\n        return dialog\n    }\n\n    class TextView {\n        var text: String = \"\"\n        var color: String = \"#00000\"\n    }\n}\n```\n\n#### Usage\n\n```kotlin\n//Function that creates dialog builder and builds Dialog\nfun dialog(init: DialogBuilder.() -\u003e Unit): Dialog {\n    return DialogBuilder(init).build()\n}\n\nval dialog: Dialog = dialog {\n    title {\n        text = \"Dialog Title\"\n    }\n    message {\n        text = \"Dialog Message\"\n        color = \"#333333\"\n    }\n    image {\n        File.createTempFile(\"image\", \"jpg\")\n    }\n}\n\ndialog.show()\n```\n\n#### Output\n\n```\nsetting title text Dialog Title\nsetting title color #00000\nshowing title\nsetting message Dialog Message\nsetting message color #333333\nshowing message\nshowing image with size 0\nshowing dialog Dialog@5f184fc6\n```\n\n[Factory Method](/patterns/src/test/kotlin/FactoryMethod.kt)\n-----------------\n\nThe 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.\n\n#### Example\n\n```kotlin\nsealed class Country {\n    object USA : Country() //Kotlin 1.0 could only be an inner class or object\n}\n\nobject Spain : Country() //Kotlin 1.1 declared as top level class/object in the same file\nclass Greece(val someProperty: String) : Country()\ndata class Canada(val someProperty: String) : Country() //Kotlin 1.1 data class extends other class\n//object Poland : Country()\n\nclass Currency(\n    val code: String\n)\n\nobject CurrencyFactory {\n\n    fun currencyForCountry(country: Country): Currency =\n        when (country) {\n            is Greece -\u003e Currency(\"EUR\")\n            is Spain -\u003e Currency(\"EUR\")\n            is Country.USA -\u003e Currency(\"USD\")\n            is Canada -\u003e Currency(\"CAD\")\n        }  //try to add a new country Poland, it won't even compile without adding new branch to 'when'\n}\n```\n\n#### Usage\n\n```kotlin\nval greeceCurrency = CurrencyFactory.currencyForCountry(Greece(\"\")).code\nprintln(\"Greece currency: $greeceCurrency\")\n\nval usaCurrency = CurrencyFactory.currencyForCountry(Country.USA).code\nprintln(\"USA currency: $usaCurrency\")\n\nassertThat(greeceCurrency).isEqualTo(\"EUR\")\nassertThat(usaCurrency).isEqualTo(\"USD\")\n```\n\n#### Output\n\n```\nGreece currency: EUR\nUS currency: USD\nUK currency: No Currency Code Available\n```\n\n[Singleton](/patterns/src/test/kotlin/Singleton.kt)\n------------\n\nThe singleton pattern ensures that only one object of a particular class is ever created.\nAll further references to objects of the singleton class refer to the same underlying instance.\nThere are very few applications, do not overuse this pattern!\n\n#### Example:\n\n```kotlin\nobject PrinterDriver {\n    init {\n        println(\"Initializing with object: $this\")\n    }\n\n    fun print() = println(\"Printing with object: $this\")\n}\n```\n\n#### Usage\n\n```kotlin\nprintln(\"Start\")\nPrinterDriver.print()\nPrinterDriver.print()\n```\n\n#### Output\n\n```\nStart\nInitializing with object: PrinterDriver@6ff3c5b5\nPrinting with object: PrinterDriver@6ff3c5b5\nPrinting with object: PrinterDriver@6ff3c5b5\n```\n\n[Abstract Factory](/patterns/src/test/kotlin/AbstractFactory.kt)\n-------------------\n\nThe abstract factory pattern is used to provide a client with a set of related or dependant objects.\nThe \"family\" of objects created by the factory are determined at run-time.\n\n#### Example\n\n```kotlin\ninterface Plant\n\nclass OrangePlant : Plant\n\nclass ApplePlant : Plant\n\nabstract class PlantFactory {\n    abstract fun makePlant(): Plant\n\n    companion object {\n        inline fun \u003creified T : Plant\u003e createFactory(): PlantFactory = when (T::class) {\n            OrangePlant::class -\u003e OrangeFactory()\n            ApplePlant::class  -\u003e AppleFactory()\n            else               -\u003e throw IllegalArgumentException()\n        }\n    }\n}\n\nclass AppleFactory : PlantFactory() {\n    override fun makePlant(): Plant = ApplePlant()\n}\n\nclass OrangeFactory : PlantFactory() {\n    override fun makePlant(): Plant = OrangePlant()\n}\n```\n\n#### Usage\n\n```kotlin\nval plantFactory = PlantFactory.createFactory\u003cOrangePlant\u003e()\nval plant = plantFactory.makePlant()\nprintln(\"Created plant: $plant\")\n```\n\n#### Output\n\n```kotlin\nCreated plant: OrangePlant@4f023edb\n```\n\nStructural\n==========\n\n\u003eIn software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.\n\u003e\n\u003e**Source:** [wikipedia.org](http://en.wikipedia.org/wiki/Structural_pattern)\n\n[Adapter](/patterns/src/test/kotlin/Adapter.kt)\n----------\n\nThe 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.\n\n#### Example\n\n```kotlin\ninterface Temperature {\n    var temperature: Double\n}\n\nclass CelsiusTemperature(override var temperature: Double) : Temperature\n\nclass FahrenheitTemperature(var celsiusTemperature: CelsiusTemperature) : Temperature {\n\n    override var temperature: Double\n        get() = convertCelsiusToFahrenheit(celsiusTemperature.temperature)\n        set(temperatureInF) {\n            celsiusTemperature.temperature = convertFahrenheitToCelsius(temperatureInF)\n        }\n\n    private fun convertFahrenheitToCelsius(f: Double): Double = (f - 32) * 5 / 9\n\n    private fun convertCelsiusToFahrenheit(c: Double): Double = (c * 9 / 5) + 32\n}\n\n```\n\n#### Usage\n\n```kotlin\nval celsiusTemperature = CelsiusTemperature(0.0)\nval fahrenheitTemperature = FahrenheitTemperature(celsiusTemperature)\n\ncelsiusTemperature.temperature = 36.6\nprintln(\"${celsiusTemperature.temperature} C -\u003e ${fahrenheitTemperature.temperature} F\")\n\nfahrenheitTemperature.temperature = 100.0\nprintln(\"${fahrenheitTemperature.temperature} F -\u003e ${celsiusTemperature.temperature} C\")\n```\n\n#### Output\n\n```\n36.6 C -\u003e 97.88000000000001 F\n100.0 F -\u003e 37.77777777777778 C\n```\n\n[Decorator](/patterns/src/test/kotlin/Decorator.kt)\n------------\n\nThe 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.\nThis provides a flexible alternative to using inheritance to modify behaviour.\n\n#### Example\n\n```kotlin\ninterface CoffeeMachine {\n    fun makeSmallCoffee()\n    fun makeLargeCoffee()\n}\n\nclass NormalCoffeeMachine : CoffeeMachine {\n    override fun makeSmallCoffee() = println(\"Normal: Making small coffee\")\n\n    override fun makeLargeCoffee() = println(\"Normal: Making large coffee\")\n}\n\n//Decorator:\nclass EnhancedCoffeeMachine(val coffeeMachine: CoffeeMachine) : CoffeeMachine by coffeeMachine {\n\n    // overriding behaviour\n    override fun makeLargeCoffee() {\n        println(\"Enhanced: Making large coffee\")\n        coffeeMachine.makeLargeCoffee()\n    }\n\n    // extended behaviour\n    fun makeCoffeeWithMilk() {\n        println(\"Enhanced: Making coffee with milk\")\n        coffeeMachine.makeSmallCoffee()\n        println(\"Enhanced: Adding milk\")\n    }\n}\n```\n\n#### Usage\n\n```kotlin\n    val normalMachine = NormalCoffeeMachine()\n    val enhancedMachine = EnhancedCoffeeMachine(normalMachine)\n\n    // non-overridden behaviour\n    enhancedMachine.makeSmallCoffee()\n    // overriding behaviour\n    enhancedMachine.makeLargeCoffee()\n    // extended behaviour\n    enhancedMachine.makeCoffeeWithMilk()\n```\n\n#### Output\n\n```\nNormal: Making small coffee\n\nEnhanced: Making large coffee\nNormal: Making large coffee\n\nEnhanced: Making coffee with milk\nNormal: Making small coffee\nEnhanced: Adding milk\n```\n\n[Facade](/patterns/src/test/kotlin/Facade.kt)\n---------\n\nThe facade pattern is used to define a simplified interface to a more complex subsystem.\n\n#### Example\n\n```kotlin\nclass ComplexSystemStore(val filePath: String) {\n\n    init {\n        println(\"Reading data from file: $filePath\")\n    }\n\n    val store = HashMap\u003cString, String\u003e()\n\n    fun store(key: String, payload: String) {\n        store.put(key, payload)\n    }\n\n    fun read(key: String): String = store[key] ?: \"\"\n\n    fun commit() = println(\"Storing cached data: $store to file: $filePath\")\n}\n\ndata class User(val login: String)\n\n//Facade:\nclass UserRepository {\n    val systemPreferences = ComplexSystemStore(\"/data/default.prefs\")\n\n    fun save(user: User) {\n        systemPreferences.store(\"USER_KEY\", user.login)\n        systemPreferences.commit()\n    }\n\n    fun findFirst(): User = User(systemPreferences.read(\"USER_KEY\"))\n}\n```\n\n#### Usage\n\n```kotlin\nval userRepository = UserRepository()\nval user = User(\"dbacinski\")\nuserRepository.save(user)\nval resultUser = userRepository.findFirst()\nprintln(\"Found stored user: $resultUser\")\n```\n\n#### Ouput\n\n```\nReading data from file: /data/default.prefs\nStoring cached data: {USER_KEY=dbacinski} to file: /data/default.prefs\nFound stored user: User(login=dbacinski)\n```\n\n[Protection Proxy](/patterns/src/test/kotlin/ProtectionProxy.kt)\n------------------\n\nThe proxy pattern is used to provide a surrogate or placeholder object, which references an underlying object.\nProtection proxy is restricting access.\n\n#### Example\n\n```kotlin\ninterface File {\n    fun read(name: String)\n}\n\nclass NormalFile : File {\n    override fun read(name: String) = println(\"Reading file: $name\")\n}\n\n//Proxy:\nclass SecuredFile : File {\n    val normalFile = NormalFile()\n    var password: String = \"\"\n\n    override fun read(name: String) {\n        if (password == \"secret\") {\n            println(\"Password is correct: $password\")\n            normalFile.read(name)\n        } else {\n            println(\"Incorrect password. Access denied!\")\n        }\n    }\n}\n```\n\n#### Usage\n\n```kotlin\nval securedFile = SecuredFile()\nsecuredFile.read(\"readme.md\")\n\nsecuredFile.password = \"secret\"\nsecuredFile.read(\"readme.md\")\n```\n\n#### Ouput\n\n```\nIncorrect password. Access denied!\nPassword is correct: secret\nReading file: readme.md\n```\n\n\n\n[Composite](/patterns/src/test/kotlin/Composite.kt)\n------------------\n\nThe composite pattern is used to compose zero-or-more similar \nobjects so that they can be manipulated as one object.\n\n#### Example\n\n```kotlin\n\nopen class Equipment(private var price: Int, private var name: String) {\n    open fun getPrice(): Int = price\n}\n\n\n/*\n[composite]\n*/\n\nopen class Composite(name: String) : Equipment(0, name) {\n    val equipments = ArrayList\u003cEquipment\u003e()\n\n    fun add(equipment: Equipment) {\n        this.equipments.add(equipment)\n    }\n\n    override fun getPrice(): Int {\n        return equipments.map { it.getPrice() }.sum()\n    }\n}\n\n\n/*\n leafs\n*/\n\nclass Cabbinet : Composite(\"cabbinet\")\nclass FloppyDisk : Equipment(70, \"Floppy Disk\")\nclass HardDrive : Equipment(250, \"Hard Drive\")\nclass Memory : Equipment(280, \"Memory\")\n\n\n```\n\n#### Usage\n\n```kotlin\nvar cabbinet = Cabbinet()\ncabbinet.add(FloppyDisk())\ncabbinet.add(HardDrive())\ncabbinet.add(Memory())\nprintln(cabbinet.getPrice())\n```\n\n#### Ouput\n\n```\n600\n```\n\n\n\nInfo\n====\n\nDescriptions from: [Gang of Four Design Patterns Reference Sheet](http://www.blackwasp.co.uk/GangOfFour.aspx)\n","funding_links":[],"categories":["Programming Language Design Patterns","Libraries","Kotlin","Navigation","DSA and System Design","GoF design patterns (Language/Framework specifc)","二、按编程语言分的核心设计模式","Language/Framework design patterns (mainly GoF)"],"sub_categories":["Code","Android samples","**其他主流语言**"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbacinski%2FDesign-Patterns-In-Kotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdbacinski%2FDesign-Patterns-In-Kotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbacinski%2FDesign-Patterns-In-Kotlin/lists"}