0Pricing
Kotlin Academy · درس

أنماط عملية

Decorators باستخدام التفويض

أنماط عملية درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

نمط المزيّن

يلفّ المزيّن كائنًا لإضافة سلوك مع الحفاظ على الواجهة نفسها. تجعل الكلمة المفتاحية by في Kotlin إنشاء المزيّنات أمرًا بسيطًا: أحِل كل شيء، وتجاوز الأجزاء التي تحسّنها فقط.

مكوّن أساسي

نبدأ بمصدر بيانات بسيط. وستغلّفه المزيّنات.

interface DataSource {
    fun fetch(): String
}

class NetworkSource : DataSource {
    override fun fetch() = "raw-data"
}

fun main() {
    println(NetworkSource().fetch())
}

مزيّن التسجيل

يفوّض المزيّن إلى المصدر المغلّف ويضيف التسجيل حول الاستدعاء الذي يهمه.

interface DataSource { fun fetch(): String }
class NetworkSource : DataSource { override fun fetch() = "raw-data" }

class LoggingSource(private val inner: DataSource) : DataSource by inner {
    override fun fetch(): String {
        println("fetching...")
        val result = inner.fetch()
        println("done")
        return result
    }
}

fun main() {
    println(LoggingSource(NetworkSource()).fetch())
}

مزيّن التخزين المؤقت

يخزّن مزيّن آخر النتيجة الأولى مؤقتًا، بحيث تتجاوز الاستدعاءات المتكررة المصدر الأساسي.

interface DataSource { fun fetch(): String }
class NetworkSource : DataSource { override fun fetch() = "raw-data" }

class CachingSource(private val inner: DataSource) : DataSource by inner {
    private var cached: String? = null
    override fun fetch(): String {
        return cached ?: inner.fetch().also { cached = it }
    }
}

fun main() {
    val s = CachingSource(NetworkSource())
    println(s.fetch())
    println(s.fetch()) // served from cache
}

تكديس المزيّنات

بما أن كل مزيّن هو نفسه DataSource، يمكنك تكديسها. فالترتيب مهم: المزيّن الخارجي يلفّ الداخلي.

interface DataSource { fun fetch(): String }
class NetworkSource : DataSource { override fun fetch() = "raw-data" }

class LoggingSource(private val inner: DataSource) : DataSource by inner {
    override fun fetch(): String { println("log"); return inner.fetch() }
}
class CachingSource(private val inner: DataSource) : DataSource by inner {
    private var c: String? = null
    override fun fetch() = c ?: inner.fetch().also { c = it }
}

fun main() {
    val s = LoggingSource(CachingSource(NetworkSource()))
    println(s.fetch())
    println(s.fetch())
}

مزيّن التحقق

يمكن للمزيّنات أيضًا التحقق من المدخلات. يتحقق المزيّن هنا قبل التفويض إلى العامل الفعلي.

interface Processor { fun process(input: String): String }
class UpperProcessor : Processor { override fun process(input: String) = input.uppercase() }

class ValidatingProcessor(private val inner: Processor) : Processor by inner {
    override fun process(input: String): String {
        require(input.isNotBlank()) { "empty input" }
        return inner.process(input)
    }
}

fun main() {
    println(ValidatingProcessor(UpperProcessor()).process("hello"))
}

غلاف مجموعة للقراءة فقط

يجعل التفويض إنشاء أغلفة المحوّلات أمرًا سهلًا. نلفّ هنا قائمة ونضيف طريقة ملخص مخصصة، مع إحالة جميع عمليات القائمة.

class SummarizedList(private val inner: List<Int>) : List<Int> by inner {
    fun total() = inner.sum()
}

fun main() {
    val list = SummarizedList(listOf(1, 2, 3))
    println(list.size)
    println(list.total())
}

عدّ الاستدعاءات

يمكن للمزيّن تتبع المقاييس بشفافية، وهو أمر مفيد للمراقبة دون المساس بالتطبيق الفعلي.

interface Service { fun call(): String }
class RealService : Service { override fun call() = "ok" }

class CountingService(private val inner: Service) : Service by inner {
    var calls = 0
        private set
    override fun call(): String {
        calls++
        return inner.call()
    }
}

fun main() {
    val s = CountingService(RealService())
    s.call(); s.call()
    println(s.calls)
}

لماذا ينجح التفويض هنا

كان إنشاء المزيّنات بالوراثة سيفرض أن تكون الفئة الأساسية open، ويربط كل مزيّن بفئة ملموسة. أما التفويض فلا يعتمد إلا على الواجهة، لذلك تظل المزيّنات ضعيفة الاقتران وقابلة للتركيب.

قائمة التحقق من النمط

لإنشاء مزيّن باستخدام التفويض:

  • استقبل الكائن المغلّف باعتباره private val
  • فوّض الواجهة باستخدام by
  • تجاوز الأعضاء التي تحسّنها فقط
  • استدعِ الكائن الداخلي داخل التجاوز

جمع الأجزاء

تنشأ المزيّنات والمحوّلات والوكلاء جميعًا بصورة طبيعية من تفويض الفئات. وبدمجها مع الواجهات الصغيرة، تتيح لك إنشاء أنظمة مرنة متعددة الطبقات يسهل اختبارها وتوسعتها.

تحقق سريع

اختبر فهمك لأنماط التفويض العملية.

مراجعة

أنشأت مزيّنات عملية باستخدام التفويض:

  • أغلفة للتسجيل والتخزين المؤقت والتحقق والعدّ
  • تكديس المزيّنات لأن كل مزيّن يستخدم الواجهة نفسها
  • تجاوز الأعضاء المحسّنة فقط؛ وإحالة بقية الأعضاء

بهذا تكتمل دورة تفويض الفئات.

الأسئلة الشائعة

هل درس «أنماط عملية» مجاني؟

نعم — نص درس «أنماط عملية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «أنماط عملية»؟

Decorators باستخدام التفويض تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «أنماط عملية»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الكلمة المفتاحية by
  2. التفويض إلى الأعضاء
  3. التفويض مقابل الوراثة
  4. أنماط عملية
← العودة إلى Kotlin Academy