أنماط التصميم في Kotlin: المستوى المتقدم مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

أنماط التصميم في Kotlin مع أمثلة: المستوى المتقدم

في المستوى المبتدئ، يتقن المطورون الأنماط الكلاسيكية: Singleton و Factory و Observer. ومع ذلك، عند بناء أنظمة معقدة وقابلة للتوسع، يلزم ضبط معماري أكثر دقة. في هذه المقالة، سنشرح أربعة أنماط تصميم متقدمة في Kotlin: Composite و Visitor و State و Bridge. سيتم توضيح كل نمط بمثال عملي للكود وشرح متى يجب استخدامه.



1. نمط Composite

يسمح نمط Composite للعملاء بالعمل بشكل موحد مع الكائنات الفردية ومجموعاتها. هذا هو الحل الأمثل لبناء الهياكل الهرمية، مثل أنظمة الملفات أو قوائم الواجهات أو المشاهد الرسومية.

في Kotlin، نستخدم غالبًا sealed classes لتمثيل عُقد الشجرة. لننظر في مثال لبناء هيكل "الملفات والمجلدات":

sealed class FileSystemNode(open val name: String) {    data class File(override val name: String, val size: Long) : FileSystemNode(name)    data class Directory(        override val name: String,        val children: MutableList<FileSystemNode> = mutableListOf()    ) : FileSystemNode(name) {        fun add(node: FileSystemNode) {            children.add(node)        }        fun remove(node: FileSystemNode) {            children.remove(node)        }        fun getTotalSize(): Long = children.sumOf {            when (it) {                is File -> it.size                is Directory -> it.getTotalSize()            }        }    }}

// الاستخدامfun main() { val root = FileSystemNode.Directory("root") root.add(FileSystemNode.File("readme.txt", 1024)) val subDir = FileSystemNode.Directory("src") subDir.add(FileSystemNode.File("main.kt", 4096)) root.add(subDir) println("الحجم الإجمالي: ${root.getTotalSize()} بايت") // 5120}

الإيجابيات: يبسط كود العميل، ويدعم العمليات التكرارية. السلبيات: قد يعقد النظام إذا كانت الشجرة عميقة جدًا.



2. نمط Visitor

يسمح Visitor بإضافة عمليات جديدة إلى الكائنات دون تغيير فئاتها. هذا مفيد بشكل خاص عندما يكون لديك تسلسل هرمي ثابت للفئات، ولكن خوارزميات المعالجة تتغير بشكل متكرر.

في Kotlin، يعمل بشكل ممتاز مع sealed classes. لننفذ مثالاً لحساب المساحة للأشكال:

sealed class Shapeclass Circle(val radius: Double) : Shape()class Rectangle(val width: Double, val height: Double) : Shape()

interface ShapeVisitor<T> { fun visit(circle: Circle): T fun visit(rectangle: Rectangle): T}

class AreaCalculator : ShapeVisitor<Double> { override fun visit(circle: Circle) = Math.PI * circle.radius * circle.radius override fun visit(rectangle: Rectangle) = rectangle.width * rectangle.height}

// الاستخدامfun <T> Shape.accept(visitor: ShapeVisitor<T>): T = when (this) { is Circle -> visitor.visit(this) is Rectangle -> visitor.visit(this)}

fun main() { val shapes = listOf(Circle(5.0), Rectangle(3.0, 4.0)) val calculator = AreaCalculator() shapes.forEach { println("المساحة: ${it.accept(calculator)}") }}

متى يتم التطبيق: إذا كان هيكل الكائنات نادرًا ما يتغير، والعمليات عليها تتغير بشكل متكرر. في Kotlin، يمكن استخدام when للحالات البسيطة، لكن Visitor يظل لا غنى عنه في المنطق المعقد مع العديد من الأنواع.



3. نمط State

يسمح نمط State للكائن بتغيير سلوكه اعتمادًا على حالته الداخلية. هذا بديل أنيق لعبارات if-else أو switch-case الضخمة.

في Kotlin، يمكننا استخدام sealed classes لتمثيل الحالات. مثال — طلب في متجر إلكتروني

المدونات

توصيات الكتب