Patrons de conception en Kotlin : techniques avancées avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Patrons de conception en Kotlin avec exemples : niveau avancé

\n\n

Les patrons de conception sont des solutions éprouvées aux problèmes courants du développement logiciel. Si vous maîtrisez déjà les patrons de base (Singleton, Factory, Observer), il est temps de passer au niveau supérieur. Dans cet article, nous allons analyser quatre patrons avancés — Chaîne de responsabilité, Interpréteur, Médiateur et Mémento — et montrer leur implémentation en Kotlin en tenant compte des idiomes du langage (sealed class, extension functions, lambdas).

\n\n

1. Chaîne de responsabilité (Chain of Responsibility)

\n\n

Objectif : Permet de transmettre une requête séquentiellement le long d'une chaîne de gestionnaires jusqu'à ce que l'un d'eux la traite.

\n\n

Problème : Un système de journalisation où les messages de différents niveaux (DEBUG, INFO, ERROR) doivent être traités par différents enregistreurs.

\n\n

Implémentation en Kotlin :

\n\n
// Gestionnaire abstrait\nabstract class Logger(private val level: Int) {\n    private var nextLogger: Logger? = null\n\n    fun setNext(logger: Logger): Logger {\n        this.nextLogger = logger\n        return logger\n    }\n\n    fun log(level: Int, message: String) {\n        if (this.level <= level) {\n            write(message)\n        }\n        nextLogger?.log(level, message)\n    }\n\n    protected abstract fun write(message: String)\n}\n\n// Gestionnaires concrets\nclass ConsoleLogger(level: Int) : Logger(level) {\n    override fun write(message: String) = println("[Console] $message")\n}\n\nclass FileLogger(level: Int) : Logger(level) {\n    override fun write(message: String) = println("[File] $message")\n}\n\nclass EmailLogger(level: Int) : Logger(level) {\n    override fun write(message: String) = println("[Email] $message")\n}\n\n// Utilisation\nfun main() {\n    val logger = ConsoleLogger(1).apply {\n        setNext(FileLogger(2))\n            .setNext(EmailLogger(3))\n    }\n    logger.log(2, "Avertissement : niveau de mémoire faible")\n    // Sortie :\n    // [Console] Avertissement : niveau de mémoire faible\n    // [File] Avertissement : niveau de mémoire faible\n}
\n\n

Avantages en Kotlin : Grâce à apply et à l'appel chaîné de setNext, le code est concis. On peut également remplacer la classe abstraite par une interface avec une implémentation par défaut.

\n\n

2. Interpréteur (Interpreter)

\n\n

Objectif : Définit la grammaire d'un langage et interprète les phrases de ce langage.

\n\n

Problème : Besoin d'analyser et d'évaluer des expressions arithmétiques simples (par exemple, "3 + 5 - 2").

\n\n

Implémentation en Kotlin avec sealed class :

\n\n
// Expression abstraite\nsealed class Expression {\n    abstract fun interpret(): Int\n}\n\n// Expression terminale — nombre\ndata class Number(val value: Int) : Expression() {\n    override fun interpret() = value\n}\n\n// Expressions non terminales — opérations\ndata class Add(val left: Expression, val right: Expression) : Expression() {\n    override fun interpret() = left.interpret() + right.interpret()\n}\n\ndata class Subtract(val left: Expression, val right: Expression) : Expression() {\n    override fun interpret() = left.interpret() - right.interpret()\n}\n\n// Analyseur (simplifié)\nfun parse(tokens: List<String>): Expression {\n    val stack = mutableListOf<Expression>()\n    var i = 0\n    while (i < tokens.size) {\n        when (tokens[i]) {\n            "+" -> {\n                val right = Number(tokens[++i].toInt())\n                val left = stack.removeLast()\n                stack.add(Add(left, right))\n            }\n            "-" -> {\n                val right = Number(tokens[++i].toInt())\n                val left = stack.removeLast()\n                stack.add(Subtract(left, right))\n            }\n            else -> stack.add(Number(tokens[i]                

Blogs

Book Recommendations