0Pricing
PHP Academy · درس

الأنماط الهيكلية: Adapter وDecorator وFacade

ركّب الكائنات وبسّط الواجهات باستخدام الأنماط الهيكلية.

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

تركيب الكائنات

تصف الأنماط الهيكلية كيفية تركيب الأصناف والكائنات في بنيات أكبر مع الحفاظ على مرونتها. نغطي ثلاثة أنماط أساسية:

  • المحوّل — يجعل الواجهة غير المتوافقة قابلة للاستخدام.
  • المزيّن — يضيف سلوكًا من دون توريث.
  • الواجهة — يقدم واجهة بسيطة لنظام فرعي معقد.

المحوّل: المشكلة

تعتمدون على واجهة PaymentGateway، لكن SDK تابعًا لجهة خارجية يوفّر chargeCard($amountInCents) ببنية مختلفة. يؤدي استدعاء SDK مباشرةً إلى تسريب واجهته البرمجية في أنحاء الشيفرة. في ما يلي، الواجهتان غير متوافقتين بوضوح — وهذا الاختلاف هو بالضبط ما يحله المحوّل.

<?php
// What our app wants to depend on
interface PaymentGateway { public function pay(float $dollars): string; }

// What the vendor actually gives us (cents, array result)
final class StripeSdk {
    public function chargeCard(int $cents): array {
        return ['id' => 'ch_1', 'amount' => $cents];
    }
}
// dollars vs cents, string vs array -> shapes don't line up
var_dump((new StripeSdk())->chargeCard(2000));

المحوّل في الشيفرة

يحتفظ المحوّل بالكائن المُحوَّل إليه ويطبّق واجهة الهدف، محوّلًا المعاملات والقيم المعادة. وتظل شيفرة التطبيق نظيفة ومستقلة عن المورّد.

<?php
interface PaymentGateway { public function pay(float $dollars): string; }

// Third-party SDK with an incompatible API
final class StripeSdk {
    public function chargeCard(int $cents): array {
        return ['id' => 'ch_1', 'amount' => $cents];
    }
}

final class StripeAdapter implements PaymentGateway {
    public function __construct(private StripeSdk $sdk) {}
    public function pay(float $dollars): string {
        $res = $this->sdk->chargeCard((int) round($dollars * 100));
        return "charged {$res['amount']}c -> {$res['id']}";
    }
}
echo (new StripeAdapter(new StripeSdk()))->pay(20.0), PHP_EOL;

المزيّن: الفكرة

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

<?php
interface Coffee { public function cost(): float; }
final class Espresso implements Coffee {
    public function cost(): float { return 2.0; }
}
final class WithMilk implements Coffee {
    public function __construct(private Coffee $inner) {}
    public function cost(): float { return $this->inner->cost() + 0.5; }
}
echo (new WithMilk(new Espresso()))->cost(), PHP_EOL; // 2.5

المزيّن في الشيفرة

يطبّق كل مزيّن الواجهة نفسها ويحتفظ بنسخة داخلية. نغلّف هنا مصدر بيانات بالتخزين المؤقت والتسجيل، ونركّبهما بحرية.

<?php
interface DataSource { public function read(): string; }

final class FileSource implements DataSource {
    public function read(): string { return 'raw-data'; }
}

final class UpperCaseDecorator implements DataSource {
    public function __construct(private DataSource $inner) {}
    public function read(): string { return strtoupper($this->inner->read()); }
}
final class ExclaimDecorator implements DataSource {
    public function __construct(private DataSource $inner) {}
    public function read(): string { return $this->inner->read() . '!!!'; }
}

$src = new ExclaimDecorator(new UpperCaseDecorator(new FileSource()));
echo $src->read(), PHP_EOL; // RAW-DATA!!!

المزيّنات في الواقع العملي

تُعد البرمجيات الوسيطة في PSR-7 وPSR-15 تطبيقًا لنمط المزيّن على معالجة HTTP؛ إذ يغلّف كل مكوّن برمجي وسيط المكوّن الذي يليه، مضيفًا المصادقة أو التسجيل أو التخزين المؤقت حول الطلب والاستجابة. كما تستخدم أغلفة التدفقات وطبقات التخزين المؤقت PSR-6/16 التزيين عادةً. والسمة الأساسية هي: يمكن استبدال الغلاف بالكائن الذي يغلّفه.

المزيّن مقارنةً بالتوريث

يثبّت التوريث السلوك في وقت الترجمة ولا يسمح إلا بصنف أساسي واحد. أما التزيين فهو ديناميكي وقابل للتركيب. اختر المزيّنات عندما:

  • تتضاعف تركيبات الميزات الاختيارية،
  • ينبغي إضافة السلوك أو إزالته أثناء التشغيل،
  • يجب توسيع صنف final أو صنف تابع لجهة خارجية لا يمكن توريثه.

الواجهة: الفكرة

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

<?php
// Without a facade, the client wires every step itself
final class Cpu { public function boot(): string { return 'cpu '; } }
final class Disk { public function load(): string { return 'disk '; } }
final class Ram { public function check(): string { return 'ram'; } }

$out = (new Cpu())->boot() . (new Disk())->load() . (new Ram())->check();
echo $out, PHP_EOL; // cpu disk ram

الواجهة في الشيفرة

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

<?php
final class Inventory { public function reserve(string $sku): bool { return true; } }
final class Payments { public function charge(float $amt): bool { return true; } }
final class Shipping { public function dispatch(string $sku): string { return 'tracking-99'; } }

final class OrderFacade {
    public function __construct(
        private Inventory $inv,
        private Payments $pay,
        private Shipping $ship
    ) {}
    public function place(string $sku, float $amount): string {
        if (!$this->inv->reserve($sku)) { return 'out of stock'; }
        if (!$this->pay->charge($amount)) { return 'payment failed'; }
        return 'shipped: ' . $this->ship->dispatch($sku);
    }
}
echo (new OrderFacade(new Inventory(), new Payments(), new Shipping()))
    ->place('ABC', 49.99), PHP_EOL;

تمييز الأنماط الثلاثة

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

اختبار عملي مفيد: يتعلق الموحّل بالتوافق، والمزيّن بالتحسين، والواجهة بالتبسيط.

ملاحظة حول واجهات Laravel

إن «واجهات» Laravel هي آلية وكيل ثابت تدعمها حاوية الخدمات، وليست نمط الواجهة الخاص بـ GoF. وهي تشترك معه في هدف توفير واجهة مريحة، لكنها تختلف عنه في طريقة التنفيذ. لا تخلطوا بين مصطلحات أطر العمل والنمط الهيكلي عند التفكير في التصميم.

فحص سريع

حدّدوا النمط انطلاقًا من هدفه.

مراجعة

ركّبتم الكائنات باستخدام ثلاثة أنماط هيكلية: المحوّل لربط الواجهات غير المتوافقة، مثل SDK تابع لمورّد، والمزيّن لتكديس السلوك أثناء التشغيل، وهو أساس البرمجيات الوسيطة في PSR-15، والواجهة لتقديم واجهة بسيطة لنظام فرعي معقد. يقلل كل نمط الاقتران، فتقاوم شيفرتكم الارتهان لمورّد واحد وتضخم الميزات.

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

هل درس «الأنماط الهيكلية: Adapter وDecorator وFacade» مجاني؟

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

ماذا ستتعلم في «الأنماط الهيكلية: Adapter وDecorator وFacade»؟

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

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

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

كم من الوقت يستغرق درس «الأنماط الهيكلية: Adapter وDecorator وFacade»؟

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

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

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

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

  1. مبادئ SOLID في التطبيق
  2. الأنماط الإنشائية: Factory وBuilder وSingleton
  3. الأنماط الهيكلية: Adapter وDecorator وFacade
  4. الأنماط السلوكية: Strategy وObserver وCommand
← العودة إلى PHP Academy