---
title: "المُزَخرِف"
type: "design-pattern"
slug: "decorator"
url: "http://localhost:3000/ar/design-patterns/decorator.md"
category: "الأنماط الهيكلية"
description: "المُزَخرِف هو نمط تصميم هيكلي يتيح لك إرفاق سلوكيات جديدة بالكائنات عن طريق وضع هذه الكائنات داخل كائنات غلاف خاصة تحتوي على هذه السلوكيات."
languages: ["java", "csharp", "cpp", "go", "php", "python", "ruby", "rust", "swift", "typescript"]
---
# المُزَخرِف

> المُزَخرِف هو نمط تصميم هيكلي يتيح لك إرفاق سلوكيات جديدة بالكائنات عن طريق وضع هذه الكائنات داخل كائنات غلاف خاصة تحتوي على هذه السلوكيات.

## Intent

**المُزَخرِف** هو نمط تصميم هيكلي يتيح لك إرفاق سلوكيات جديدة بالكائنات عن طريق وضع هذه الكائنات داخل كائنات غلاف خاصة تحتوي على هذه السلوكيات.

## Problem

تخيّل أنك تعمل على مكتبة إشعارات تتيح للبرامج الأخرى إخطار مستخدميها بالأحداث المهمة.

استندت النسخة الأولية من المكتبة على فئة `Notifier` التي كانت تحتوي على بضعة حقول فقط ومنشئ وأسلوب `send` واحد. كان الأسلوب يقبل وسيطة رسالة من العميل ويرسلها إلى قائمة بريدية مُمرَّرة إلى المُخطِر عبر منشئه. كان من المفترض أن يُنشئ تطبيق الطرف الثالث الذي يعمل بوصفه عميلاً كائن المُخطِر ويُهيّئه مرةً واحدة، ثم يستخدمه في كل مرة يقع فيها حدث مهم.

يمكن للبرنامج استخدام فئة المُخطِر لإرسال إشعارات عن الأحداث المهمة إلى مجموعة محددة مسبقًا من عناوين البريد الإلكتروني.

في مرحلة ما، تدرك أن مستخدمي المكتبة يتوقعون أكثر من مجرد إشعارات بريدية. يريد كثيرون منهم تلقّي رسائل SMS عن المشكلات الحرجة. ويريد آخرون تلقّي إشعارات على Facebook، وبطبيعة الحال يودّ المستخدمون في بيئات الشركات تلقّي إشعارات Slack.

يُنفَّذ كل نوع إشعار كفئة فرعية من المُخطِر.

ما مدى صعوبة ذلك؟ وسّعت فئة `Notifier` ووضعت أساليب الإشعار الإضافية في فئات فرعية جديدة. كان يُفترض بعدها أن يُنشئ العميل الفئة المطلوبة ويستخدمها لجميع الإشعارات اللاحقة.

لكن طرح عليك أحدهم سؤالاً منطقيًا، "لماذا لا تستخدم أنواعًا متعددة من الإشعارات في آنٍ واحد؟ فإذا اشتعلت النار في منزلك، ستريد على الأرجح أن تُبلَّغ عبر كل قناة."

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

انفجار تركيبي في الفئات الفرعية.

يتعين عليك إيجاد طريقة أخرى لهيكلة فئات الإشعارات حتى لا يكسر عددها أي رقم قياسي في موسوعة غينيس.

## Solution

توسيع الفئة هو أول ما يتبادر إلى الذهن عندما تحتاج إلى تعديل سلوك الكائن. غير أن الوراثة تنطوي على عدة محاذير جدية ينبغي الانتباه لها.

* الوراثة ثابتة. لا يمكنك تعديل سلوك كائن موجود في وقت التشغيل. يمكنك فقط استبداله بكائن آخر مُنشأ من فئة فرعية مختلفة.
* يمكن للفئات الفرعية أن يكون لها فئة أصل واحدة فقط. في أغلب اللغات، لا تسمح الوراثة لفئة بأن ترث سلوكيات فئات متعددة في آنٍ واحد.

إحدى طرق التغلب على هذه المحاذير هي استخدام _التجميع_ أو _التركيب_ _التجميع_: يحتوي الكائن A على الكائنات B؛ يمكن لـ B العيش دون A.
_التركيب_: يتكون الكائن A من الكائنات B؛ يدير A دورة حياة B؛ لا يمكن لـ B العيش دون A. بدلاً من _الوراثة_. يعمل كلا البديلين بنفس الطريقة تقريبًا: يمتلك أحد الكائنات مرجعًا لكائن آخر ويفوّض إليه بعض الأعمال، في حين أن الكائن في الوراثة _قادر_ بنفسه على القيام بهذا العمل بوراثة السلوك من فئته الأصل.

بهذا النهج الجديد يمكنك بسهولة استبدال كائن “المساعد” المرتبط بآخر، مما يغيّر سلوك الحاوية في وقت التشغيل. يمكن للكائن استخدام سلوك فئات مختلفة عبر امتلاك مراجع لكائنات متعددة وتفويضها جميع أنواع الأعمال. التجميع/التركيب هو المبدأ الأساسي وراء أنماط تصميم كثيرة بما فيها المُزَخرِف. وعلى ذكر النمط، فلنعد إلى مناقشته.

الوراثة مقابل التجميع

“الغلاف” هو الاسم البديل لنمط المُزَخرِف الذي يعبّر بوضوح عن الفكرة الرئيسية للنمط. _الغلاف_ هو كائن يمكن ربطه بكائن _هدف_ معين. يحتوي الغلاف على نفس مجموعة الأساليب الموجودة في الهدف ويفوّض إليه جميع الطلبات التي يتلقاها. غير أن الغلاف قد يعدّل النتيجة بفعل شيء ما قبل أو بعد تمرير الطلب إلى الهدف.

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

في مثال الإشعارات لدينا، لنترك سلوك الإشعار البريدي البسيط داخل فئة `Notifier` الأساسية ونحوّل جميع أساليب الإشعار الأخرى إلى مزخرفات.

Various notification methods become decorators.

سيحتاج كود العميل إلى تغليف كائن المُخطِر الأساسي في مجموعة من المزخرفات التي تتناسب مع تفضيلات العميل. ستكون الكائنات الناتجة منظمة على شكل مكدس.

Apps might configure complex stacks of notification decorators.

سيكون المزخرف الأخير في المكدس هو الكائن الذي يتعامل معه العميل فعليًا. بما أن جميع المزخرفات تنفّذ نفس الواجهة كالمُخطِر الأساسي، فلن يهتم بقية كود العميل بمعرفة ما إذا كان يعمل مع كائن المُخطِر “الصافي” أم المزخرَف.

يمكننا تطبيق نفس النهج على سلوكيات أخرى كتنسيق الرسائل أو تأليف قائمة المستلمين. يمكن للعميل تزخرف الكائن بأي مزخرفات مخصصة، طالما أنها تتبع نفس الواجهة التي تتبعها الأخرى.

## Structure

1. يُعلن **المكوّن** عن الواجهة المشتركة لكل من الأغلفة والكائنات المُغلَّفة.
2. **المكوّن الملموس** هو فئة الكائنات التي يجري تغليفها. يُعرّف السلوك الأساسي الذي يمكن للمزخرفات تعديله.
3. تمتلك فئة **المزخرف الأساسي** حقلاً للإشارة إلى الكائن المُغلَّف. ينبغي إعلان نوع الحقل بنوع واجهة المكوّن حتى يمكنه احتواء المكوّنات الملموسة والمزخرفات على حد سواء. يفوّض المزخرف الأساسي جميع العمليات إلى الكائن المُغلَّف.
4. تُعرِّف **المزخرفات الملموسة** سلوكيات إضافية يمكن إضافتها إلى المكوّنات ديناميكيًا. تتجاوز المزخرفات الملموسة أساليب المزخرف الأساسي وتنفّذ سلوكها قبل أو بعد استدعاء الأسلوب الأصلي.
5. يمكن لـ**العميل** تغليف المكوّنات في طبقات متعددة من المزخرفات، طالما يتعامل مع جميع الكائنات عبر واجهة المكوّن.

## Pseudocode

في هذا المثال، يتيح لك نمط **المُزَخرِف** ضغط البيانات الحساسة وتشفيرها بصورة مستقلة عن الشيفرة التي تستخدم هذه البيانات فعليًا.

The encryption and compression decorators example.

يُغلّف التطبيق كائن مصدر البيانات بزوج من المزخرفات. يغيّر كلا الغلافين الطريقة التي تُكتب بها البيانات إلى القرص وتُقرأ منه:

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

تنفّذ المزخرفات وفئة مصدر البيانات نفس الواجهة، مما يجعلها قابلة للتبادل بالكامل في كود العميل.

// تُعرِّف واجهة المكوّن العمليات التي يمكن
// للمزخرفات تعديلها.
interface DataSource is
    method writeData(data)
    method readData():data

// توفر المكوّنات الملموسة تطبيقات افتراضية
// للعمليات. قد تكون هناك عدة متغيرات من هذه
// الفئات في البرنامج.
class FileDataSource implements DataSource is
    constructor FileDataSource(filename) { ... }

    method writeData(data) is
        // كتابة البيانات إلى الملف.

    method readData():data is
        // قراءة البيانات من الملف.

// تتبع فئة المزخرف الأساسي نفس الواجهة كبقية المكوّنات.
// الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف
// لجميع المزخرفات الملموسة. قد يتضمن التطبيق الافتراضي
// لكود التغليف حقلاً لتخزين مكوّن مُغلَّف ووسائل تهيئته.
class DataSourceDecorator implements DataSource is
    protected field wrappee: DataSource

    constructor DataSourceDecorator(source: DataSource) is
        wrappee = source

    // يفوّض المزخرف الأساسي جميع الأعمال ببساطة إلى
    // المكوّن المُغلَّف. يمكن إضافة سلوكيات إضافية في
    // المزخرفات الملموسة.
    method writeData(data) is
        wrappee.writeData(data)

    // قد تستدعي المزخرفات الملموسة التطبيق الأصلي للعملية
    // بدلاً من استدعاء الكائن المُغلَّف مباشرة. يبسّط
    // هذا النهج توسيع فئات المزخرف.
    method readData():data is
        return wrappee.readData()

// يجب أن تستدعي المزخرفات الملموسة أساليب الكائن المُغلَّف،
// لكنها قد تضيف شيئًا خاصًا بها إلى النتيجة. يمكن
// للمزخرفات تنفيذ السلوك المضاف قبل أو بعد الاستدعاء
// إلى كائن مُغلَّف.
class EncryptionDecorator extends DataSourceDecorator is
    method writeData(data) is
        // 1. تشفير البيانات الممررة.
        // 2. تمرير البيانات المُشفَّرة إلى طريقة writeData
        // الخاصة بـ wrappee.

    method readData():data is
        // 1. الحصول على البيانات من طريقة readData الخاصة بـ wrappee.
        // 2. محاولة فك تشفيرها إذا كانت مُشفَّرة.
        // 3. إرجاع النتيجة.

// يمكنك تغليف الكائنات في عدة طبقات من المزخرفات.
class CompressionDecorator extends DataSourceDecorator is
    method writeData(data) is
        // 1. ضغط البيانات الممررة.
        // 2. تمرير البيانات المضغوطة إلى طريقة writeData
        // الخاصة بـ wrappee.

    method readData():data is
        // 1. الحصول على البيانات من طريقة readData الخاصة بـ wrappee.
        // 2. محاولة فك ضغطها إذا كانت مضغوطة.
        // 3. إرجاع النتيجة.

// الخيار الأول. مثال بسيط على تجميع المزخرف.
class Application is
    method dumbUsageExample() is
        source = new FileDataSource("somefile.dat")
        source.writeData(salaryRecords)
        // تمت كتابة الملف الهدف ببيانات عادية.

        source = new CompressionDecorator(source)
        source.writeData(salaryRecords)
        // تمت كتابة الملف الهدف ببيانات
        // مضغوطة.

        source = new EncryptionDecorator(source)
        // يحتوي المتغير source الآن على هذا:
        // Encryption > Compression > FileDataSource
        source.writeData(salaryRecords)
        // تمت كتابة الملف ببيانات مضغوطة
        // ومُشفَّرة.

// الخيار الثاني. كود عميل يستخدم مصدر بيانات خارجي.
// لا تعرف كائنات SalaryManager تفاصيل التخزين ولا تكترث لها.
// تعمل مع مصدر بيانات مُهيَّأ مسبقًا تتلقاه من مُهيِّئ التطبيق.
class SalaryManager is
    field source: DataSource

    constructor SalaryManager(source: DataSource) { ... }

    method load() is
        return source.readData()

    method save() is
        source.writeData(salaryRecords)
    // ...طرق مفيدة أخرى...

// يمكن للتطبيق تجميع مكدسات مختلفة من المزخرفات
// في وقت التشغيل بحسب الإعداد أو البيئة.
class ApplicationConfigurator is
    method configurationExample() is
        source = new FileDataSource("salary.dat")
        if (enabledEncryption)
            source = new EncryptionDecorator(source)
        if (enabledCompression)
            source = new CompressionDecorator(source)

        logger = new SalaryManager(source)
        salary = logger.load()
    // ...

## Applicability

استخدم نمط المُزَخرِف عندما تحتاج إلى إسناد سلوكيات إضافية للكائنات في وقت التشغيل دون كسر الشيفرة التي تستخدم هذه الكائنات.

 يتيح لك المُزَخرِف تنظيم منطق أعمالك في طبقات، وإنشاء مزخرف لكل طبقة وتأليف الكائنات بتركيبات متنوعة من هذا المنطق في وقت التشغيل. يمكن لكود العميل التعامل مع جميع هذه الكائنات بنفس الطريقة، إذ تتبع جميعها واجهة مشتركة.

 استخدم النمط عندما يكون توسيع سلوك الكائن بالوراثة أمرًا محرجًا أو غير ممكن.

 تحتوي كثير من لغات البرمجة على الكلمة المفتاحية `final` التي يمكن استخدامها لمنع توسيع الفئة. بالنسبة للفئة النهائية، الطريقة الوحيدة لإعادة استخدام السلوك الموجود هي تغليف الفئة بغلافك الخاص باستخدام نمط المُزَخرِف.

## How to Implement

1. تأكد من إمكانية تمثيل مجال أعمالك كمكوّن أساسي مع طبقات اختيارية متعددة فوقه.
2. حدد الأساليب المشتركة بين المكوّن الأساسي والطبقات الاختيارية. أنشئ واجهة مكوّن وأعلن عن تلك الأساليب فيها.
3. أنشئ فئة مكوّن ملموس وعرّف فيها السلوك الأساسي.
4. أنشئ فئة مزخرف أساسي. يجب أن تحتوي على حقل لتخزين مرجع إلى الكائن المُغلَّف. ينبغي الإعلان عن الحقل بنوع واجهة المكوّن للسماح بالربط بالمكوّنات الملموسة والمزخرفات على حد سواء. يجب على المزخرف الأساسي تفويض جميع الأعمال إلى الكائن المُغلَّف.
5. تأكد من أن جميع الفئات تطبّق واجهة المكوّن.
6. أنشئ مزخرفات ملموسة بتمديدها من المزخرف الأساسي. يجب أن ينفّذ المزخرف الملموس سلوكه قبل أو بعد استدعاء الأسلوب الأصلي (الذي يفوّض دائمًا إلى الكائن المُغلَّف).
7. يجب أن يكون كود العميل مسؤولاً عن إنشاء المزخرفات وتأليفها بالطريقة التي يحتاجها العميل.

## Pros

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

## Cons

* يصعب إزالة غلاف معين من مكدس الأغلفة.
* يصعب تنفيذ مزخرف بحيث لا يعتمد سلوكه على الترتيب في مكدس المزخرفات.
* قد تبدو الشيفرة الأولية لتكوين الطبقات قبيحة نوعًا ما.

## Relations with Other Patterns

* [المحوّل](/ar/design-patterns/adapter) يوفر واجهة مختلفة تمامًا للوصول إلى كائن موجود. في المقابل، مع نمط [المُزَخرِف](/ar/design-patterns/decorator) تبقى الواجهة كما هي أو يُوسَّع نطاقها. علاوةً على ذلك، يدعم _المُزَخرِف_ التأليف التكراري الذي لا يمكن تحقيقه باستخدام _المحوّل_.
* مع [المحوّل](/ar/design-patterns/adapter) تصل إلى كائن موجود عبر واجهة مختلفة. مع [الوكيل](/ar/design-patterns/proxy)، تبقى الواجهة كما هي. مع [المُزَخرِف](/ar/design-patterns/decorator) تصل إلى الكائن عبر واجهة مُحسَّنة.
* [سلسلة المسؤولية](/ar/design-patterns/chain-of-responsibility) و[المُزَخرِف](/ar/design-patterns/decorator) لهما بنيتا فئة متشابهتان جدًا. يعتمد كلا النمطين على التأليف التكراري لتمرير التنفيذ عبر سلسلة من الكائنات. غير أن ثمة فروقات جوهرية عدة.
يمكن لمعالجات _CoR_ تنفيذ عمليات اعتباطية بشكل مستقل عن بعضها، كما يمكنها إيقاف تمرير الطلب في أي نقطة. في المقابل، يمكن لمختلف _المزخرفات_ توسيع سلوك الكائن مع الحفاظ على اتساقه مع الواجهة الأساسية. فضلاً عن ذلك، لا يُسمح للمزخرفات بكسر تدفق الطلب.
* [المركّب](/ar/design-patterns/composite) و[المُزَخرِف](/ar/design-patterns/decorator) لهما مخططا بنية متشابهان إذ يعتمدان على التأليف التكراري لتنظيم عدد غير محدد من الكائنات.
_المُزَخرِف_ يشبه _المركّب_ لكن له مكوّن ابن واحد فقط. وثمة فارق جوهري آخر: _المُزَخرِف_ يضيف مسؤوليات إضافية إلى الكائن المُغلَّف، بينما يكتفي _المركّب_ بـ“جمع” نتائج أبنائه.
غير أن النمطين يمكنهما أيضًا التعاون: يمكنك استخدام _المُزَخرِف_ لتوسيع سلوك كائن معين في شجرة _المركّب_.
* يمكن للتصميمات التي تعتمد اعتمادًا كبيرًا على [المركّب](/ar/design-patterns/composite) و[المُزَخرِف](/ar/design-patterns/decorator) الاستفادة في الغالب من استخدام [النموذج الأولي](/ar/design-patterns/prototype). يتيح تطبيق النمط استنساخ البنى المعقدة بدلاً من إعادة بنائها من الصفر.
* [المُزَخرِف](/ar/design-patterns/decorator) يتيح لك تغيير مظهر الكائن، بينما يتيح لك [الاستراتيجية](/ar/design-patterns/strategy) تغيير جوهره.
* [المُزَخرِف](/ar/design-patterns/decorator) و[الوكيل](/ar/design-patterns/proxy) لهما بنيتان متشابهتان لكن نوايا مختلفة جدًا. يقوم كلا النمطين على مبدأ التأليف، حيث يُفترض بكائن ما أن يفوّض بعض الأعمال إلى كائن آخر. الفارق هو أن _الوكيل_ عادةً ما يدير دورة حياة كائن الخدمة بنفسه، في حين يخضع تأليف _المزخرفات_ دائمًا لسيطرة العميل.
## Relations

**Related patterns**

- [المهايئ (Adapter)](/ar/design-patterns/adapter.md)
- [الوكيل](/ar/design-patterns/proxy.md)
- [سلسلة المسؤوليات](/ar/design-patterns/chain-of-responsibility.md)
- [المركَّب](/ar/design-patterns/composite.md)
- [النموذج الأولي (Prototype)](/ar/design-patterns/prototype.md)
- [الاستراتيجية](/ar/design-patterns/strategy.md)

## Code Examples

### java

```java
package refactoring_guru.decorator.example.decorators;

public interface DataSource {
    void writeData(String data);

    String readData();
}

package refactoring_guru.decorator.example.decorators;

import java.io.*;

public class FileDataSource implements DataSource {
    private String name;

    public FileDataSource(String name) {
        this.name = name;
    }

    @Override
    public void writeData(String data) {
        File file = new File(name);
        try (OutputStream fos = new FileOutputStream(file)) {
            fos.write(data.getBytes(), 0, data.length());
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

    @Override
    public String readData() {
        char[] buffer = null;
        File file = new File(name);
        try (FileReader reader = new FileReader(file)) {
            buffer = new char[(int) file.length()];
            reader.read(buffer);
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
        return new String(buffer);
    }
}

package refactoring_guru.decorator.example.decorators;

public abstract class DataSourceDecorator implements DataSource {
    private DataSource wrappee;

    DataSourceDecorator(DataSource source) {
        this.wrappee = source;
    }

    @Override
    public void writeData(String data) {
        wrappee.writeData(data);
    }

    @Override
    public String readData() {
        return wrappee.readData();
    }
}

package refactoring_guru.decorator.example.decorators;

import java.util.Base64;

public class EncryptionDecorator extends DataSourceDecorator {

    public EncryptionDecorator(DataSource source) {
        super(source);
    }

    @Override
    public void writeData(String data) {
        super.writeData(encode(data));
    }

    @Override
    public String readData() {
        return decode(super.readData());
    }

    private String encode(String data) {
        byte[] result = data.getBytes();
        for (int i = 0; i < result.length; i++) {
            result[i] += (byte) 1;
        }
        return Base64.getEncoder().encodeToString(result);
    }

    private String decode(String data) {
        byte[] result = Base64.getDecoder().decode(data);
        for (int i = 0; i < result.length; i++) {
            result[i] -= (byte) 1;
        }
        return new String(result);
    }
}

package refactoring_guru.decorator.example.decorators;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;

public class CompressionDecorator extends DataSourceDecorator {
    private int compLevel = 6;

    public CompressionDecorator(DataSource source) {
        super(source);
    }

    public int getCompressionLevel() {
        return compLevel;
    }

    public void setCompressionLevel(int value) {
        compLevel = value;
    }

    @Override
    public void writeData(String data) {
        super.writeData(compress(data));
    }

    @Override
    public String readData() {
        return decompress(super.readData());
    }

    private String compress(String stringData) {
        byte[] data = stringData.getBytes();
        try {
            ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
            DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel));
            dos.write(data);
            dos.close();
            bout.close();
            return Base64.getEncoder().encodeToString(bout.toByteArray());
        } catch (IOException ex) {
            return null;
        }
    }

    private String decompress(String stringData) {
        byte[] data = Base64.getDecoder().decode(stringData);
        try {
            InputStream in = new ByteArrayInputStream(data);
            InflaterInputStream iin = new InflaterInputStream(in);
            ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
            int b;
            while ((b = iin.read()) != -1) {
                bout.write(b);
            }
            in.close();
            iin.close();
            bout.close();
            return new String(bout.toByteArray());
        } catch (IOException ex) {
            return null;
        }
    }
}

package refactoring_guru.decorator.example;

import refactoring_guru.decorator.example.decorators.*;

public class Demo {
    public static void main(String[] args) {
        String salaryRecords = "Name,Salary\nJohn Smith,100000\nSteven Jobs,912000";
        DataSourceDecorator encoded = new CompressionDecorator(
                                         new EncryptionDecorator(
                                             new FileDataSource("out/OutputDemo.txt")));
        encoded.writeData(salaryRecords);
        DataSource plain = new FileDataSource("out/OutputDemo.txt");

        System.out.println("- Input ----------------");
        System.out.println(salaryRecords);
        System.out.println("- Encoded --------------");
        System.out.println(plain.readData());
        System.out.println("- Decoded --------------");
        System.out.println(encoded.readData());
    }
}

- Input ----------------
Name,Salary
John Smith,100000
Steven Jobs,912000
- Encoded --------------
Zkt7e1Q5eU8yUm1Qe0ZsdHJ2VXp6dDBKVnhrUHtUe0sxRUYxQkJIdjVLTVZ0dVI5Q2IwOXFISmVUMU5rcENCQmdxRlByaD4+
- Decoded --------------
Name,Salary
John Smith,100000
Steven Jobs,912000
```

### csharp

```csharp
using System;

namespace RefactoringGuru.DesignPatterns.Composite.Conceptual
{
    // واجهة Component الأساسية تُعرِّف العمليات التي يمكن
    // للمزخرفات تعديلها.
    public abstract class Component
    {
        public abstract string Operation();
    }

    // توفر المكوّنات الملموسة تطبيقات افتراضية للعمليات.
    // قد تكون هناك عدة متغيرات من هذه الفئات.
    class ConcreteComponent : Component
    {
        public override string Operation()
        {
            return "ConcreteComponent";
        }
    }

    // تتبع فئة Decorator الأساسية نفس الواجهة كبقية المكوّنات.
    // الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف
    // لجميع المزخرفات الملموسة. قد يتضمن التطبيق الافتراضي
    // لكود التغليف حقلاً لتخزين المكوّن المُغلَّف ووسائل تهيئته.
    abstract class Decorator : Component
    {
        protected Component _component;

        public Decorator(Component component)
        {
            this._component = component;
        }

        public void SetComponent(Component component)
        {
            this._component = component;
        }

        // يفوّض المزخرف جميع الأعمال إلى المكوّن المُغلَّف.
        public override string Operation()
        {
            if (this._component != null)
            {
                return this._component.Operation();
            }
            else
            {
                return string.Empty;
            }
        }
    }

    // تستدعي المزخرفات الملموسة الكائن المُغلَّف وتعدّل نتيجته بطريقة ما.
    class ConcreteDecoratorA : Decorator
    {
        public ConcreteDecoratorA(Component comp) : base(comp)
        {
        }

        // قد تستدعي المزخرفات التطبيق الأصلي للعملية بدلاً
        // من استدعاء الكائن المُغلَّف مباشرة. يبسّط هذا النهج
        // توسيع فئات المزخرف.
        public override string Operation()
        {
            return $"ConcreteDecoratorA({base.Operation()})";
        }
    }

    // يمكن للمزخرفات تنفيذ سلوكها قبل أو بعد الاستدعاء
    // إلى كائن مُغلَّف.
    class ConcreteDecoratorB : Decorator
    {
        public ConcreteDecoratorB(Component comp) : base(comp)
        {
        }

        public override string Operation()
        {
            return $"ConcreteDecoratorB({base.Operation()})";
        }
    }
    
    public class Client
    {
        // يعمل كود العميل مع جميع الكائنات باستخدام واجهة Component.
        // يمكنه بهذه الطريقة البقاء مستقلاً عن الفئات الملموسة
        // للمكوّنات التي يتعامل معها.
        public void ClientCode(Component component)
        {
            Console.WriteLine("RESULT: " + component.Operation());
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();

            var simple = new ConcreteComponent();
            Console.WriteLine("Client: I get a simple component:");
            client.ClientCode(simple);
            Console.WriteLine();

            // ...وكذلك المزخرفة منها.
            //
            // لاحظ كيف يمكن للمزخرفات تغليف ليس فقط المكوّنات
            // البسيطة بل المزخرفات الأخرى أيضًا.
            ConcreteDecoratorA decorator1 = new ConcreteDecoratorA(simple);
            ConcreteDecoratorB decorator2 = new ConcreteDecoratorB(decorator1);
            Console.WriteLine("Client: Now I've got a decorated component:");
            client.ClientCode(decorator2);
        }
    }
}

Client: I get a simple component:
RESULT: ConcreteComponent

Client: Now I've got a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
```

### cpp

```cpp
/**
 * واجهة Component الأساسية تُعرِّف العمليات التي يمكن
 * للمزخرفات تعديلها.
 */
class Component {
 public:
  virtual ~Component() {}
  virtual std::string Operation() const = 0;
};
/**
 * توفر المكوّنات الملموسة تطبيقات افتراضية للعمليات.
 * قد تكون هناك عدة متغيرات من هذه الفئات.
 */
class ConcreteComponent : public Component {
 public:
  std::string Operation() const override {
    return "ConcreteComponent";
  }
};
/**
 * تتبع فئة Decorator الأساسية نفس الواجهة كبقية المكوّنات.
 * الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف
 * لجميع المزخرفات الملموسة. قد يتضمن التطبيق الافتراضي
 * لكود التغليف حقلاً لتخزين المكوّن المُغلَّف ووسائل تهيئته.
 */
class Decorator : public Component {
  /**
   * @var Component
   */
 protected:
  Component* component_;

 public:
  Decorator(Component* component) : component_(component) {
  }
  /**
   * يفوّض المزخرف جميع الأعمال إلى المكوّن المُغلَّف.
   */
  std::string Operation() const override {
    return this->component_->Operation();
  }
};
/**
 * تستدعي المزخرفات الملموسة الكائن المُغلَّف وتعدّل نتيجته بطريقة ما.
 */
class ConcreteDecoratorA : public Decorator {
  /**
   * قد تستدعي المزخرفات التطبيق الأصلي للعملية بدلاً من
   * استدعاء الكائن المُغلَّف مباشرة. يبسّط هذا النهج
   * توسيع فئات المزخرف.
   */
 public:
  ConcreteDecoratorA(Component* component) : Decorator(component) {
  }
  std::string Operation() const override {
    return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
  }
};
/**
 * يمكن للمزخرفات تنفيذ سلوكها قبل أو بعد الاستدعاء
 * إلى كائن مُغلَّف.
 */
class ConcreteDecoratorB : public Decorator {
 public:
  ConcreteDecoratorB(Component* component) : Decorator(component) {
  }

  std::string Operation() const override {
    return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
  }
};
/**
 * يعمل كود العميل مع جميع الكائنات باستخدام واجهة Component.
 * يمكنه بهذه الطريقة البقاء مستقلاً عن الفئات الملموسة
 * للمكوّنات التي يتعامل معها.
 */
void ClientCode(Component* component) {
  // ...
  std::cout << "RESULT: " << component->Operation();
  // ...
}

int main() {
  /**
   * يمكن لكود العميل بهذه الطريقة دعم المكوّنات البسيطة...
   */
  Component* simple = new ConcreteComponent;
  std::cout << "Client: I've got a simple component:\n";
  ClientCode(simple);
  std::cout << "\n\n";
  /**
   * ...وكذلك المزخرفة منها.
   *
   * لاحظ كيف يمكن للمزخرفات تغليف ليس فقط المكوّنات البسيطة
   * بل المزخرفات الأخرى أيضًا.
   */
  Component* decorator1 = new ConcreteDecoratorA(simple);
  Component* decorator2 = new ConcreteDecoratorB(decorator1);
  std::cout << "Client: Now I've got a decorated component:\n";
  ClientCode(decorator2);
  std::cout << "\n";

  delete simple;
  delete decorator1;
  delete decorator2;

  return 0;
}

Client: I've got a simple component:
RESULT: ConcreteComponent

Client: Now I've got a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
```

### go

```go
package main

type IPizza interface {
	getPrice() int
}

package main

type VeggieMania struct {
}

func (p *VeggieMania) getPrice() int {
	return 15
}

package main

type TomatoTopping struct {
	pizza IPizza
}

func (c *TomatoTopping) getPrice() int {
	pizzaPrice := c.pizza.getPrice()
	return pizzaPrice + 7
}

package main

type CheeseTopping struct {
	pizza IPizza
}

func (c *CheeseTopping) getPrice() int {
	pizzaPrice := c.pizza.getPrice()
	return pizzaPrice + 10
}

package main

import "fmt"

func main() {

	pizza := &VeggieMania{}

	//إضافة طبقة الجبن
	pizzaWithCheese := &CheeseTopping{
		pizza: pizza,
	}

	//إضافة طبقة الطماطم
	pizzaWithCheeseAndTomato := &TomatoTopping{
		pizza: pizzaWithCheese,
	}

	fmt.Printf("Price of veggeMania with tomato and cheese topping is %d\n", pizzaWithCheeseAndTomato.getPrice())
}

Price of veggeMania with tomato and cheese topping is 32
```

### php

```php
<?php

namespace RefactoringGuru\Decorator\Conceptual;

/**
 * واجهة Component الأساسية تُعرِّف العمليات التي يمكن
 * للمزخرفات تعديلها.
 */
interface Component
{
    public function operation(): string;
}

/**
 * توفر المكوّنات الملموسة تطبيقات افتراضية للعمليات.
 * قد تكون هناك عدة متغيرات من هذه الفئات.
 */
class ConcreteComponent implements Component
{
    public function operation(): string
    {
        return "ConcreteComponent";
    }
}

/**
 * تتبع فئة Decorator الأساسية نفس الواجهة كبقية المكوّنات.
 * الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف
 * لجميع المزخرفات الملموسة. قد يتضمن التطبيق الافتراضي
 * لكود التغليف حقلاً لتخزين المكوّن المُغلَّف ووسائل تهيئته.
 */
class Decorator implements Component
{
    /**
     * @var Component
     */
    protected $component;

    public function __construct(Component $component)
    {
        $this->component = $component;
    }

    /**
     * يفوّض المزخرف جميع الأعمال إلى المكوّن المُغلَّف.
     */
    public function operation(): string
    {
        return $this->component->operation();
    }
}

/**
 * تستدعي المزخرفات الملموسة الكائن المُغلَّف وتعدّل نتيجته بطريقة ما.
 */
class ConcreteDecoratorA extends Decorator
{
    /**
     * قد تستدعي المزخرفات التطبيق الأصلي للعملية بدلاً من
     * استدعاء الكائن المُغلَّف مباشرة. يبسّط هذا النهج
     * توسيع فئات المزخرف.
     */
    public function operation(): string
    {
        return "ConcreteDecoratorA(" . parent::operation() . ")";
    }
}

/**
 * يمكن للمزخرفات تنفيذ سلوكها قبل أو بعد الاستدعاء
 * إلى كائن مُغلَّف.
 */
class ConcreteDecoratorB extends Decorator
{
    public function operation(): string
    {
        return "ConcreteDecoratorB(" . parent::operation() . ")";
    }
}

/**
 * يعمل كود العميل مع جميع الكائنات باستخدام واجهة Component.
 * يمكنه بهذه الطريقة البقاء مستقلاً عن الفئات الملموسة
 * للمكوّنات التي يتعامل معها.
 */
function clientCode(Component $component)
{
    // ...

    echo "RESULT: " . $component->operation();

    // ...
}

/**
 * يمكن لكود العميل بهذه الطريقة دعم المكوّنات البسيطة...
 */
$simple = new ConcreteComponent();
echo "Client: I've got a simple component:\n";
clientCode($simple);
echo "\n\n";

/**
 * ...وكذلك المزخرفة منها.
 *
 * لاحظ كيف يمكن للمزخرفات تغليف ليس فقط المكوّنات البسيطة
 * بل المزخرفات الأخرى أيضًا.
 */
$decorator1 = new ConcreteDecoratorA($simple);
$decorator2 = new ConcreteDecoratorB($decorator1);
echo "Client: Now I've got a decorated component:\n";
clientCode($decorator2);

Client: I've got a simple component:
RESULT: ConcreteComponent

Client: Now I've got a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))

<?php

namespace RefactoringGuru\Decorator\RealWorld;

/**
 * تُعلن واجهة المكوّن عن أسلوب فلترة يجب أن تنفّذه
 * جميع المكوّنات الملموسة والمزخرفات.
 */
interface InputFormat
{
    public function formatText(string $text): string;
}

/**
 * المكوّن الملموس هو العنصر الأساسي للتزخرف. يحتوي
 * على النص الأصلي كما هو دون أي فلترة أو تنسيق.
 */
class TextInput implements InputFormat
{
    public function formatText(string $text): string
    {
        return $text;
    }
}

/**
 * لا تحتوي فئة المزخرف الأساسي على منطق فلترة أو تنسيق حقيقي.
 * غرضها الأساسي هو تنفيذ البنية الأساسية للتزخرف:
 * حقل لتخزين مكوّن مُغلَّف أو مزخرف آخر وأسلوب التنسيق
 * الأساسي الذي يفوّض العمل إلى الكائن المُغلَّف. العمل الفعلي
 * للتنسيق تقوم به الفئات الفرعية.
 */
class TextFormat implements InputFormat
{
    /**
     * @var InputFormat
     */
    protected $inputFormat;

    public function __construct(InputFormat $inputFormat)
    {
        $this->inputFormat = $inputFormat;
    }

    /**
     * يفوّض المزخرف جميع الأعمال إلى مكوّن مُغلَّف.
     */
    public function formatText(string $text): string
    {
        return $this->inputFormat->formatText($text);
    }
}

/**
 * يُزيل هذا المزخرف الملموس جميع وسوم HTML من النص المُعطى.
 */
class PlainTextFilter extends TextFormat
{
    public function formatText(string $text): string
    {
        $text = parent::formatText($text);
        return strip_tags($text);
    }
}

/**
 * يُزيل هذا المزخرف الملموس وسوم وسمات HTML الخطرة فقط
 * التي قد تُفضي إلى ثغرة XSS.
 */
class DangerousHTMLTagsFilter extends TextFormat
{
    private $dangerousTagPatterns = [
        "|<script.*?>([\s\S]*)?</script>|i", // ...
    ];

    private $dangerousAttributes = [
        "onclick", "onkeypress", // ...
    ];


    public function formatText(string $text): string
    {
        $text = parent::formatText($text);

        foreach ($this->dangerousTagPatterns as $pattern) {
            $text = preg_replace($pattern, '', $text);
        }

        foreach ($this->dangerousAttributes as $attribute) {
            $text = preg_replace_callback('|<(.*?)>|', function ($matches) use ($attribute) {
                $result = preg_replace("|$attribute=|i", '', $matches[1]);
                return "<" . $result . ">";
            }, $text);
        }

        return $text;
    }
}

/**
 * يوفر هذا المزخرف الملموس تحويلاً أوليًا من Markdown إلى HTML.
 */
class MarkdownFormat extends TextFormat
{
    public function formatText(string $text): string
    {
        $text = parent::formatText($text);

        // تنسيق عناصر الكتلة.
        $chunks = preg_split('|\n\n|', $text);
        foreach ($chunks as &$chunk) {
            // تنسيق العناوين.
            if (preg_match('|^#+|', $chunk)) {
                $chunk = preg_replace_callback('|^(#+)(.*?)$|', function ($matches) {
                    $h = strlen($matches[1]);
                    return "<h$h>" . trim($matches[2]) . "</h$h>";
                }, $chunk);
            } // تنسيق الفقرات.
            else {
                $chunk = "<p>$chunk</p>";
            }
        }
        $text = implode("\n\n", $chunks);

        // تنسيق العناصر المضمّنة.
        $text = preg_replace("|__(.*?)__|", '<strong>$1</strong>', $text);
        $text = preg_replace("|\*\*(.*?)\*\*|", '<strong>$1</strong>', $text);
        $text = preg_replace("|_(.*?)_|", '<em>$1</em>', $text);
        $text = preg_replace("|\*(.*?)\*|", '<em>$1</em>', $text);

        return $text;
    }
}


/**
 * قد يكون كود العميل جزءًا من موقع ويب حقيقي يُقدِّم محتوى
 * أنشأه المستخدمون. بما أنه يعمل مع المُنسِّقات عبر واجهة
 * المكوّن، فلا يهمه ما إذا كان يحصل على كائن مكوّن بسيط أم مُزَخرَف.
 */
function displayCommentAsAWebsite(InputFormat $format, string $text)
{
    // ..

    echo $format->formatText($text);

    // ..
}

/**
 * تُعدّ مُنسِّقات الإدخال مفيدة جدًا عند التعامل مع المحتوى الذي ينشئه المستخدمون.
 * قد يكون عرض هذا المحتوى كما هو أمرًا خطيرًا للغاية، خاصةً عندما
 * يمكن للمستخدمين المجهولين إنشاؤه (مثل التعليقات). موقعك لا يخاطر
 * فقط بالحصول على كميات ضخمة من الروابط غير المرغوب بها بل قد يتعرض
 * أيضًا لهجمات XSS.
 */
$dangerousComment = <<<HERE
Hello! Nice blog post!
Please visit my <a href='http://www.iwillhackyou.com'>homepage</a>.
<script src="http://www.iwillhackyou.com/script.js">
  performXSSAttack();
</script>
HERE;

/**
 * عرض التعليقات بشكل ساذج (غير آمن).
 */
$naiveInput = new TextInput();
echo "Website renders comments without filtering (unsafe):\n";
displayCommentAsAWebsite($naiveInput, $dangerousComment);
echo "\n\n\n";

/**
 * عرض التعليقات بعد الفلترة (آمن).
 */
$filteredInput = new PlainTextFilter($naiveInput);
echo "Website renders comments after stripping all tags (safe):\n";
displayCommentAsAWebsite($filteredInput, $dangerousComment);
echo "\n\n\n";


/**
 * يتيح المزخرف تكديس صيغ إدخال متعددة للحصول على تحكم
 * دقيق في المحتوى المُقدَّم.
 */
$dangerousForumPost = <<<HERE
# Welcome

This is my first post on this **gorgeous** forum.

<script src="http://www.iwillhackyou.com/script.js">
  performXSSAttack();
</script>
HERE;

/**
 * عرض المنشور بشكل ساذج (غير آمن، بلا تنسيق).
 */
$naiveInput = new TextInput();
echo "Website renders a forum post without filtering and formatting (unsafe, ugly):\n";
displayCommentAsAWebsite($naiveInput, $dangerousForumPost);
echo "\n\n\n";

/**
 * مُنسِّق Markdown + فلترة الوسوم الخطرة (آمن، أنيق).
 */
$text = new TextInput();
$markdown = new MarkdownFormat($text);
$filteredInput = new DangerousHTMLTagsFilter($markdown);
echo "Website renders a forum post after translating markdown markup" .
    " and filtering some dangerous HTML tags and attributes (safe, pretty):\n";
displayCommentAsAWebsite($filteredInput, $dangerousForumPost);
echo "\n\n\n";

Website renders comments without filtering (unsafe):
Hello! Nice blog post!
Please visit my <a href='http://www.iwillhackyou.com'>homepage</a>.
<script src="http://www.iwillhackyou.com/script.js">
  performXSSAttack();
</script>


Website renders comments after stripping all tags (safe):
Hello! Nice blog post!
Please visit my homepage.

  performXSSAttack();



Website renders a forum post without filtering and formatting (unsafe, ugly):
# Welcome

This is my first post on this **gorgeous** forum.

<script src="http://www.iwillhackyou.com/script.js">
  performXSSAttack();
</script>


Website renders a forum post after translating markdown markupand filtering some dangerous HTML tags and attributes (safe, pretty):
<h1>Welcome</h1>

<p>This is my first post on this <strong>gorgeous</strong> forum.</p>

<p></p>
```

### python

```python
class Component():
    """
    واجهة Component الأساسية تُعرِّف العمليات التي يمكن للمزخرفات تعديلها.
    """

    def operation(self) -> str:
        pass


class ConcreteComponent(Component):
    """
    توفر المكوّنات الملموسة تطبيقات افتراضية للعمليات.
    قد تكون هناك عدة متغيرات من هذه الفئات.
    """

    def operation(self) -> str:
        return "ConcreteComponent"


class Decorator(Component):
    """
    تتبع فئة Decorator الأساسية نفس الواجهة كبقية المكوّنات.
    الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف لجميع المزخرفات الملموسة.
    قد يتضمن التطبيق الافتراضي لكود التغليف حقلاً لتخزين مكوّن
    مُغلَّف ووسائل تهيئته.
    """

    _component: Component = None

    def __init__(self, component: Component) -> None:
        self._component = component

    @property
    def component(self) -> Component:
        """
        يفوّض المزخرف جميع الأعمال إلى المكوّن المُغلَّف.
        """

        return self._component

    def operation(self) -> str:
        return self._component.operation()


class ConcreteDecoratorA(Decorator):
    """
    تستدعي المزخرفات الملموسة الكائن المُغلَّف وتعدّل نتيجته بطريقة ما.
    """

    def operation(self) -> str:
        """
        قد تستدعي المزخرفات التطبيق الأصلي للعملية بدلاً من استدعاء الكائن
        المُغلَّف مباشرة. يبسّط هذا النهج توسيع فئات المزخرف.
        """
        return f"ConcreteDecoratorA({self.component.operation()})"


class ConcreteDecoratorB(Decorator):
    """
    يمكن للمزخرفات تنفيذ سلوكها قبل أو بعد الاستدعاء إلى كائن مُغلَّف.
    """

    def operation(self) -> str:
        return f"ConcreteDecoratorB({self.component.operation()})"


def client_code(component: Component) -> None:
    """
    يعمل كود العميل مع جميع الكائنات باستخدام واجهة Component.
    يمكنه بهذه الطريقة البقاء مستقلاً عن الفئات الملموسة
    للمكوّنات التي يتعامل معها.
    """

    # ...

    print(f"RESULT: {component.operation()}", end="")

    # ...


if __name__ == "__main__":
    # يمكن لكود العميل بهذه الطريقة دعم المكوّنات البسيطة...
    simple = ConcreteComponent()
    print("Client: I've got a simple component:")
    client_code(simple)
    print("\n")

    # ...وكذلك المزخرفة منها.
    #
    # لاحظ كيف يمكن للمزخرفات تغليف ليس فقط المكوّنات البسيطة
    # بل المزخرفات الأخرى أيضًا.
    decorator1 = ConcreteDecoratorA(simple)
    decorator2 = ConcreteDecoratorB(decorator1)
    print("Client: Now I've got a decorated component:")
    client_code(decorator2)

Client: I've got a simple component:
RESULT: ConcreteComponent

Client: Now I've got a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
```

### ruby

```ruby
# واجهة Component الأساسية تُعرِّف العمليات التي يمكن للمزخرفات تعديلها.
class Component
  # @return [String]
  def operation
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# توفر المكوّنات الملموسة تطبيقات افتراضية للعمليات.
# قد تكون هناك عدة متغيرات من هذه الفئات.
class ConcreteComponent < Component
  # @return [String]
  def operation
    'ConcreteComponent'
  end
end

# تتبع فئة Decorator الأساسية نفس الواجهة كبقية المكوّنات.
# الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف لجميع
# المزخرفات الملموسة. قد يتضمن التطبيق الافتراضي لكود التغليف
# حقلاً لتخزين مكوّن مُغلَّف ووسائل تهيئته.
class Decorator < Component
  attr_accessor :component

  # @param [Component] component
  def initialize(component)
    @component = component
  end

  # يفوّض المزخرف جميع الأعمال إلى المكوّن المُغلَّف.
  def operation
    @component.operation
  end
end

# تستدعي المزخرفات الملموسة الكائن المُغلَّف وتعدّل نتيجته بطريقة ما.
class ConcreteDecoratorA < Decorator
  # قد تستدعي المزخرفات التطبيق الأصلي للعملية بدلاً من
  # استدعاء الكائن المُغلَّف مباشرة. يبسّط هذا النهج
  # توسيع فئات المزخرف.
  def operation
    "ConcreteDecoratorA(#{@component.operation})"
  end
end

# يمكن للمزخرفات تنفيذ سلوكها قبل أو بعد الاستدعاء إلى كائن مُغلَّف.
class ConcreteDecoratorB < Decorator
  # @return [String]
  def operation
    "ConcreteDecoratorB(#{@component.operation})"
  end
end

# يعمل كود العميل مع جميع الكائنات باستخدام واجهة Component.
# يمكنه بهذه الطريقة البقاء مستقلاً عن الفئات الملموسة للمكوّنات التي يتعامل معها.
def client_code(component)
  # ...

  print "RESULT: #{component.operation}"

  # ...
end

# يمكن لكود العميل بهذه الطريقة دعم المكوّنات البسيطة...
simple = ConcreteComponent.new
puts 'Client: I\'ve got a simple component:'
client_code(simple)
puts "\n\n"

# ...وكذلك المزخرفة منها.
#
# لاحظ كيف يمكن للمزخرفات تغليف ليس فقط المكوّنات البسيطة
# بل المزخرفات الأخرى أيضًا.
decorator1 = ConcreteDecoratorA.new(simple)
decorator2 = ConcreteDecoratorB.new(decorator1)
puts 'Client: Now I\'ve got a decorated component:'
client_code(decorator2)

Client: I've got a simple component:
RESULT: ConcreteComponent

Client: Now I've got a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
```

### rust

```rust
let mut input = BufReader::new(Cursor::new("Input data"));
input.read(&mut buf).ok();

use std::io::{BufReader, Cursor, Read};

fn main() {
    let mut buf = [0u8; 10];

    // يُزَخرِف القارئ المُوَسَّد قارئ المتجه الذي يُغلِّف بيانات الإدخال.
    let mut input = BufReader::new(Cursor::new("Input data"));

    input.read(&mut buf).ok();

    print!("Read from a buffered reader: ");

    for byte in buf {
        print!("{}", char::from(byte));
    }

    println!();
}

Read from a buffered reader: Input data
```

### swift

```swift
import XCTest

/// واجهة Component الأساسية تُعرِّف العمليات التي يمكن للمزخرفات تعديلها.
protocol Component {

    func operation() -> String
}

/// توفر المكوّنات الملموسة تطبيقات افتراضية للعمليات.
/// قد تكون هناك عدة متغيرات من هذه الفئات.
class ConcreteComponent: Component {

    func operation() -> String {
        return "ConcreteComponent"
    }
}

/// تتبع فئة Decorator الأساسية نفس الواجهة كبقية المكوّنات.
/// الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف لجميع
/// المزخرفات الملموسة. قد يتضمن التطبيق الافتراضي لكود التغليف
/// حقلاً لتخزين مكوّن مُغلَّف ووسائل تهيئته.
class Decorator: Component {

    private var component: Component

    init(_ component: Component) {
        self.component = component
    }

    /// يفوّض المزخرف جميع الأعمال إلى المكوّن المُغلَّف.
    func operation() -> String {
        return component.operation()
    }
}

/// تستدعي المزخرفات الملموسة الكائن المُغلَّف وتعدّل نتيجته بطريقة ما.
class ConcreteDecoratorA: Decorator {

    /// قد تستدعي المزخرفات التطبيق الأصلي للعملية بدلاً من
    /// استدعاء الكائن المُغلَّف مباشرة. يبسّط هذا النهج
    /// توسيع فئات المزخرف.
    override func operation() -> String {
        return "ConcreteDecoratorA(" + super.operation() + ")"
    }
}

/// يمكن للمزخرفات تنفيذ سلوكها قبل أو بعد الاستدعاء إلى كائن مُغلَّف.
class ConcreteDecoratorB: Decorator {

    override func operation() -> String {
        return "ConcreteDecoratorB(" + super.operation() + ")"
    }
}

/// يعمل كود العميل مع جميع الكائنات باستخدام واجهة Component.
/// يمكنه بهذه الطريقة البقاء مستقلاً عن الفئات الملموسة
/// للمكوّنات التي يتعامل معها.
class Client {
    // ...
    static func someClientCode(component: Component) {
        print("Result: " + component.operation())
    }
    // ...
}

/// لنرَ كيف تعمل هذه المكوّنات معًا.
class DecoratorConceptual: XCTestCase {

    func testDecoratorConceptual() {
        // يمكن لكود العميل بهذه الطريقة دعم المكوّنات البسيطة...
        print("Client: I've got a simple component")
        let simple = ConcreteComponent()
        Client.someClientCode(component: simple)

        // ...وكذلك المزخرفة منها.
        //
        // لاحظ كيف يمكن للمزخرفات تغليف ليس فقط المكوّنات البسيطة
        // بل المزخرفات الأخرى أيضًا.
        let decorator1 = ConcreteDecoratorA(simple)
        let decorator2 = ConcreteDecoratorB(decorator1)
        print("\nClient: Now I've got a decorated component")
        Client.someClientCode(component: decorator2)
    }
}

Client: I've got a simple component
Result: ConcreteComponent

Client: Now I've got a decorated component
Result: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))

import UIKit
import XCTest


protocol ImageEditor: CustomStringConvertible {

    func apply() -> UIImage
}

class ImageDecorator: ImageEditor {

    private var editor: ImageEditor

    required init(_ editor: ImageEditor) {
        self.editor = editor
    }

    func apply() -> UIImage {
        print(editor.description + " applies changes")
        return editor.apply()
    }

    var description: String {
        return "ImageDecorator"
    }
}

extension UIImage: ImageEditor {

    func apply() -> UIImage {
        return self
    }

    open override var description: String {
        return "Image"
    }
}



class BaseFilter: ImageDecorator {

    fileprivate var filter: CIFilter?

    init(editor: ImageEditor, filterName: String) {
        self.filter = CIFilter(name: filterName)
        super.init(editor)
    }

    required init(_ editor: ImageEditor) {
        super.init(editor)
    }

    override func apply() -> UIImage {

        let image = super.apply()
        let context = CIContext(options: nil)

        filter?.setValue(CIImage(image: image), forKey: kCIInputImageKey)

        guard let output = filter?.outputImage else { return image }
        guard let coreImage = context.createCGImage(output, from: output.extent) else {
            return image
        }
        return UIImage(cgImage: coreImage)
    }

    override var description: String {
        return "BaseFilter"
    }
}

class BlurFilter: BaseFilter {

    required init(_ editor: ImageEditor) {
        super.init(editor: editor, filterName: "CIGaussianBlur")
    }

    func update(radius: Double) {
        filter?.setValue(radius, forKey: "inputRadius")
    }

    override var description: String {
        return "BlurFilter"
    }
}

class ColorFilter: BaseFilter {

    required init(_ editor: ImageEditor) {
        super.init(editor: editor, filterName: "CIColorControls")
    }

    func update(saturation: Double) {
        filter?.setValue(saturation, forKey: "inputSaturation")
    }

    func update(brightness: Double) {
        filter?.setValue(brightness, forKey: "inputBrightness")
    }

    func update(contrast: Double) {
        filter?.setValue(contrast, forKey: "inputContrast")
    }

    override var description: String {
        return "ColorFilter"
    }
}

class Resizer: ImageDecorator {

    private var xScale: CGFloat = 0
    private var yScale: CGFloat = 0
    private var hasAlpha = false

    convenience init(_ editor: ImageEditor, xScale: CGFloat = 0, yScale: CGFloat = 0, hasAlpha: Bool = false) {
        self.init(editor)
        self.xScale = xScale
        self.yScale = yScale
        self.hasAlpha = hasAlpha
    }

    required init(_ editor: ImageEditor) {
        super.init(editor)
    }

    override func apply() -> UIImage {

        let image = super.apply()

        let size = image.size.applying(CGAffineTransform(scaleX: xScale, y: yScale))

        UIGraphicsBeginImageContextWithOptions(size, !hasAlpha, UIScreen.main.scale)
        image.draw(in: CGRect(origin: .zero, size: size))

        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return scaledImage ?? image
    }

    override var description: String {
        return "Resizer"
    }
}


class DecoratorRealWorld: XCTestCase {

    func testDecoratorRealWorld() {

        let image = loadImage()

        print("Client: set up an editors stack")
        let resizer = Resizer(image, xScale: 0.2, yScale: 0.2)

        let blurFilter = BlurFilter(resizer)
        blurFilter.update(radius: 2)

        let colorFilter = ColorFilter(blurFilter)
        colorFilter.update(contrast: 0.53)
        colorFilter.update(brightness: 0.12)
        colorFilter.update(saturation: 4)

        clientCode(editor: colorFilter)
    }

    func clientCode(editor: ImageEditor) {
        let image = editor.apply()
        /// ملاحظة. يمكنك إيقاف التنفيذ في Xcode لرؤية معاينة الصورة.
        print("Client: all changes have been applied for \(image)")
    }
}

private extension DecoratorRealWorld {

    func loadImage() -> UIImage {

        let urlString = "https:// refactoring.guru/images/content-public/logos/logo-new-3x.png"

        /// ملاحظة:
        /// لا تقم بتنزيل الصور بهذه الطريقة في كود الإنتاج.

        guard let url = URL(string: urlString) else {
            fatalError("Please enter a valid URL")
        }

        guard let data = try? Data(contentsOf: url) else {
            fatalError("Cannot load an image")
        }

        guard let image = UIImage(data: data) else {
            fatalError("Cannot create an image from data")
        }
        return image
    }
}

Client: set up an editors stack

BlurFilter applies changes
Resizer applies changes
Image applies changes

Client: all changes have been applied for Image
```

### typescript

```typescript
/**
 * واجهة Component الأساسية تُعرِّف العمليات التي يمكن
 * للمزخرفات تعديلها.
 */
interface Component {
    operation(): string;
}

/**
 * توفر المكوّنات الملموسة تطبيقات افتراضية للعمليات.
 * قد تكون هناك عدة متغيرات من هذه الفئات.
 */
class ConcreteComponent implements Component {
    public operation(): string {
        return 'ConcreteComponent';
    }
}

/**
 * تتبع فئة Decorator الأساسية نفس الواجهة كبقية المكوّنات.
 * الغرض الأساسي من هذه الفئة هو تعريف واجهة التغليف
 * لجميع المزخرفات الملموسة. قد يتضمن التطبيق الافتراضي
 * لكود التغليف حقلاً لتخزين المكوّن المُغلَّف ووسائل تهيئته.
 */
class Decorator implements Component {
    protected component: Component;

    constructor(component: Component) {
        this.component = component;
    }

    /**
     * يفوّض المزخرف جميع الأعمال إلى المكوّن المُغلَّف.
     */
    public operation(): string {
        return this.component.operation();
    }
}

/**
 * تستدعي المزخرفات الملموسة الكائن المُغلَّف وتعدّل نتيجته بطريقة ما.
 */
class ConcreteDecoratorA extends Decorator {
    /**
     * قد تستدعي المزخرفات التطبيق الأصلي للعملية بدلاً من
     * استدعاء الكائن المُغلَّف مباشرة. يبسّط هذا النهج
     * توسيع فئات المزخرف.
     */
    public operation(): string {
        return `ConcreteDecoratorA(${super.operation()})`;
    }
}

/**
 * يمكن للمزخرفات تنفيذ سلوكها قبل أو بعد الاستدعاء
 * إلى كائن مُغلَّف.
 */
class ConcreteDecoratorB extends Decorator {
    public operation(): string {
        return `ConcreteDecoratorB(${super.operation()})`;
    }
}

/**
 * يعمل كود العميل مع جميع الكائنات باستخدام واجهة Component.
 * يمكنه بهذه الطريقة البقاء مستقلاً عن الفئات الملموسة
 * للمكوّنات التي يتعامل معها.
 */
function clientCode(component: Component) {
    // ...

    console.log(`RESULT: ${component.operation()}`);

    // ...
}

/**
 * يمكن لكود العميل بهذه الطريقة دعم المكوّنات البسيطة...
 */
const simple = new ConcreteComponent();
console.log('Client: I\'ve got a simple component:');
clientCode(simple);
console.log('');

/**
 * ...وكذلك المزخرفة منها.
 *
 * لاحظ كيف يمكن للمزخرفات تغليف ليس فقط المكوّنات البسيطة
 * بل المزخرفات الأخرى أيضًا.
 */
const decorator1 = new ConcreteDecoratorA(simple);
const decorator2 = new ConcreteDecoratorB(decorator1);
console.log('Client: Now I\'ve got a decorated component:');
clientCode(decorator2);

Client: I've got a simple component:
RESULT: ConcreteComponent

Client: Now I've got a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
```

