Files

title, shortTitle, category, language, tag
title shortTitle category language tag
Decorator Decorator Structural ar
Gang of Four
Extensibility

المعروف أيضا باسم

التغليف

الهدف

إضافة مسؤوليات إضافية إلى كائن بطريقة ديناميكية. يوفر الزخرفة بديلاً مرنًا للوراثة لتوسيع الوظائف.

الشرح

مثال من العالم الحقيقي

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

ببساطة

يتيح لك نمط الزخرفة تغيير سلوك كائن ديناميكيًا أثناء وقت التشغيل من خلال تغليفه في كائن من فئة الزخرفة.

يقول Wikipedia

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

مثال برمجي

لنأخذ مثال التيرول. في البداية لدينا SimpleTroll الذي ينفذ الواجهة Troll:

public interface Troll {
  void atacar();
  int getPoderAtaque();
  void huirBatalla();
}

@Slf4j
public class SimpleTroll implements Troll {

  @Override
  public void atacar() {
    LOGGER.info("¡El troll intenta atraparte!");
  }

  @Override
  public int getPoderAtaque() {
    return 10;
  }

  @Override
  public void huirBatalla() {
    LOGGER.info("¡El troll chilla de horror y huye!");
  }
}

بعد ذلك، نريد إضافة عصا للتيرول. يمكننا فعل ذلك بشكل ديناميكي باستخدام الزخرفة:

@Slf4j
public class TrollConGarrote implements Troll {

  private final Troll decorado;

  public TrollConGarrote(Troll decorado) {
    this.decorado = decorado;
  }

  @Override
  public void atacar() {
    decorado.atacar();
    LOGGER.info("¡El troll te golpea con un garrote!");
  }

  @Override
  public int getPoderAtaque() {
    return decorado.getPoderAtaque() + 10;
  }

  @Override
  public void huirBatalla() {
    decorado.huirBatalla();
  }
}

إليك التيرول في العمل:

// التيرول البسيط
LOGGER.info("تيرول ذو مظهر بسيط يقترب.");
var troll = new SimpleTroll();
troll.atacar();
troll.huirBatalla();
LOGGER.info("قوة التيرول البسيط: {}.\n", troll.getPoderAtaque());

// تغيير سلوك التيرول البسيط عن طريق إضافة ديكور
LOGGER.info("تيرول يحمل عصا ضخمة يفاجئك.");
var trollConGarrote = new TrollConGarrote(troll);
trollConGarrote.atacar();
trollConGarrote.huirBatalla();
LOGGER.info("قوة التيرول مع العصا: {}.\n", trollConGarrote.getPoderAtaque());

نتيجة البرنامج:

تيرول ذو مظهر بسيط يقترب.
!التيرول يحاول الإمساك بك!
!التيرول يصرخ من الرعب ويهرب!
قوة التيرول البسيط: 10.

تيرول يحمل عصا ضخمة يفاجئك.
!التيرول يحاول الإمساك بك!
!التيرول يضربك بعصا ضخمة!
!التيرول يصرخ من الرعب ويهرب!
قوة التيرول مع العصا: 20.

مخطط الفئات

alt text

القابلية للتطبيق

يُستخدم نمط الديكور لـ:

  • إضافة مسؤوليات إلى كائنات فردية بشكل ديناميكي وشفاف، أي دون التأثير على الكائنات الأخرى.
  • للمسؤوليات التي يمكن إزالتها.
  • عندما يكون التوسيع بواسطة الفئات الفرعية غير عملي. في بعض الأحيان، قد يكون من الممكن إضافة عدد كبير من الامتدادات المستقلة التي قد تؤدي إلى انفجار في الفئات الفرعية لدعم كل مجموعة من التركيبات. أو قد تكون تعريفات الفئات مخفية أو غير متاحة للفئات الفرعية.

الدروس التعليمية

الاستخدامات المعروفة

الاعتمادات