Design patterns: Facade – With Kotlin example

Facade pattern comes under structural patterns group, it aims to simplify connection between clients and complex subsystems by providing a simple interface that contains the needed functionalities by clients and redirect requests to the handlers in the subsystem. Lets see the following diagram

In this diagram there is a subsystem with many classes and the clients are forces to access the majority of them to gain some features which causes a lot of dependencies in client code and that can lead to making the maintenance harder. Lets see what will happen after applying Facade pattern:

Now the clients do not need to access any class on the subsystem, they just request the required feature from the facade without caring of how it will deliver this feature or which subsystem’s class will handle the request, therefore the maintenance and upgrade to new version becomes easier because all changes will occur in facade without affecting clients.

Lets move forward and take a practical example by using Facade pattern to simplify the interactions in translation application.

In this example the client pass to facade interface a text with its current language’s name and a target language’s name, then facade will complete the process of translation by using the needed class to translate the text to the target language.

enum class Language {
    English,
    Italian,
    French;
}

interface Translator {
    fun translate(text: String, textLanguage: Language)
}

class ItalianTranslator : Translator {
    override fun translate(text: String, textLanguage: Language) {
        println("Translate ($text) from ${textLanguage.name} to Italian")
    }
}

class FrenchTranslator : Translator {
    override fun translate(text: String, textLanguage: Language) {
        println("Translate ($text) from ${textLanguage.name} to French")
    }
}

class EnglishTranslator : Translator {
    override fun translate(text: String, textLanguage: Language) {
        println("Translate ($text) from ${textLanguage.name} to English")
    }
}

Now let’s consider the facade

class TranslationManager {
    private val italianTranslator = ItalianTranslator()
    private val frenchTranslator = FrenchTranslator()
    private val englishTranslator = EnglishTranslator()

    fun translate(text: String, translateFrom: Language, translateTo: Language) {
        when (translateTo) {
            Language.Italian -> italianTranslator.translate(text, translateFrom)
            Language.French -> frenchTranslator.translate(text, translateFrom)
            Language.English -> englishTranslator.translate(text, translateFrom)
        }
    }
}

 

fun main() {
    val translationManager = TranslationManager()
    translationManager.translate("Some text", Language.English, Language.Italian)
    translationManager.translate("Some text", Language.English, Language.French)
}

Output:

Translate (Some text) from English to Italian
Translate (Some text) from English to French

 

Use facade pattern when you want to provide a simple interface to a complex subsystem , to divide subsystem into layers by using facade to define an entry point to each subsystem level and simplify the dependencies between subsystems by making them communicate with each other solely through their facades.


Leave a Reply

Your email address will not be published. Required fields are marked *