"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > نمط تصميم الوكيل

نمط تصميم الوكيل

تم النشر بتاريخ 2024-11-06
تصفح:246

Proxy Design Pattern

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

نمط تصميم الوكيل في جافا سكريبت

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

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

متى نحتاج إلى نمط الوكيل؟

يكون نمط الوكيل مفيدًا بشكل خاص عندما:

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

مكونات نمط الوكيل

  1. الموضوع: الواجهة التي تحدد العمليات المشتركة لكل من الكائن الحقيقي والوكيل.
  2. RealSubject: الكائن الفعلي الذي ينفذ العمل الحقيقي.
  3. الوكيل: الوسيط الذي يتحكم في الوصول إلى RealSubject.

القياس:

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

وفي هذا التشبيه:

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

تشبيه العالم الحقيقي:

فكر في الوكيل العقاري كوكيل. عندما ترغب في شراء منزل، لا تقوم بزيارة كل منزل على الفور (تحميل الكائن الحقيقي). وبدلاً من ذلك، يعرض لك الوكيل العقاري (الوكيل) أولاً الصور والأوصاف. فقط عندما تكون مستعدًا للشراء (أي عند الاتصال بـ Display())، يقوم الوكيل بترتيب زيارة منزلية (تحميل الكائن الحقيقي).

مثال من العالم الحقيقي: تحميل الصور (الوكيل الافتراضي)

لنستخدم مثال تحميل الصور في تطبيق ويب حيث نريد تأخير تحميل الصورة حتى يطلبها المستخدم (تحميل كسول). يمكن أن يعمل الوكيل كعنصر نائب حتى يتم تحميل الصورة الحقيقية.

إليك كيفية تنفيذ نمط تصميم الوكيل في JavaScript.

مثال: وكيل لتحميل الصور

// Step 1: The real object
class RealImage {
  constructor(filename) {
    this.filename = filename;
    this.loadImageFromDisk();
  }

  loadImageFromDisk() {
    console.log(`Loading ${this.filename} from disk...`);
  }

  display() {
    console.log(`Displaying ${this.filename}`);
  }
}

// Step 2: The proxy object
class ProxyImage {
  constructor(filename) {
    this.realImage = null; // no real image yet
    this.filename = filename;
  }

  display() {
    if (this.realImage === null) {
      // load the real image only when needed
      this.realImage = new RealImage(this.filename);
    }
    this.realImage.display(); // display the real image
  }
}

// Step 3: Using the proxy to display the image
const image = new ProxyImage("photo.jpg");
image.display(); // Loads and displays the image
image.display(); // Just displays the image (already loaded)

توضيح:

1). الصورة الحقيقية:

  • تمثل فئة RealImage الصورة الفعلية.
  • يأخذ اسم ملف كمدخل ويحاكي عملية تحميل الصورة من القرص التي تستغرق وقتًا طويلاً (كما هو موضح بواسطة طريقة التحميل ImageFromDiskkm).
  • بمجرد التحميل، يتم استخدام طريقة العرض لإظهار الصورة.

2). صورة الوكيل:

  • تعمل فئة ProxyImageclass كبديل لـ RealImage. ولا يتم تحميل الصورة الحقيقية على الفور.
  • يحتوي على إشارة إلى الصورة الحقيقية (لكنها في البداية فارغة لأن الصورة الحقيقية لم يتم تحميلها بعد).
  • عند استدعاء طريقة العرض على الوكيل، فإنه يتحقق مما إذا تم تحميل الصورة الحقيقية. إذا لم يكن الأمر كذلك، فإنه يقوم بتحميله أولاً، ثم يعرضه.

3). الاستخدام:

  • عندما نقوم بإنشاء مثيل لـ ProxyImage، لم يتم تحميل الصورة الفعلية بعد (لأنها كثيفة الاستخدام للموارد).
  • عند استدعاء العرض لأول مرة، يقوم الوكيل بتحميل الصورة (باستخدام فئة RealImage) ثم يعرضها.
  • يتم استدعاء العرض للمرة الثانية، وقد تم بالفعل تحميل الصورة الحقيقية، لذلك يتم عرض الصورة فقط دون تحميلها مرة أخرى.

كائن الوكيل المدمج

يتكون الوكيل ES6 من مُنشئ الوكيل الذي يقبل الهدف والمعالج كوسائط

const proxy = new Proxy(target, handler)

هنا، يمثل الهدف الكائن الذي يتم تطبيق الوكيل عليه، بينما المعالج هو كائن خاص يحدد سلوك الوكيل.

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

دعونا نفهم ذلك من خلال تطبيق الآلة الحاسبة باستخدام الوكيل المدمج

// Step 1: Define the Calculator class with prototype methods
class Calculator {
  constructor() {
    this.result = 0;
  }

  // Prototype method to add numbers
  add(a, b) {
    this.result = a   b;
    return this.result;
  }

  // Prototype method to subtract numbers
  subtract(a, b) {
    this.result = a - b;
    return this.result;
  }

  // Prototype method to multiply numbers
  multiply(a, b) {
    this.result = a * b;
    return this.result;
  }

  // Prototype method to divide numbers
  divide(a, b) {
    if (b === 0) throw new Error("Division by zero is not allowed.");
    this.result = a / b;
    return this.result;
  }
}

// Step 2: Create a proxy handler to intercept operations
const handler = {
  // Intercept 'get' operations to ensure access to prototype methods
  get(target, prop, receiver) {
    if (prop in target) {
      console.log(`Accessing property: ${prop}`);
      return Reflect.get(target, prop, receiver); // Access property safely
    } else {
      throw new Error(`Property "${prop}" does not exist.`);
    }
  },

  // Intercept 'set' operations to prevent mutation
  set(target, prop, value) {
    throw new Error(`Cannot modify property "${prop}". The calculator is immutable.`);
  }
};

// Step 3: Create a proxy instance that inherits the Calculator prototype
const calculator = new Calculator(); // Original calculator object
const proxiedCalculator = new Proxy(calculator, handler); // Proxy wrapping the calculator

// Step 4: Use the proxy instance
try {
  console.log(proxiedCalculator.add(5, 3)); // Output: 8
  console.log(proxiedCalculator.multiply(4, 2)); // Output: 8
  console.log(proxiedCalculator.divide(10, 2)); // Output: 5

  // Attempt to access prototype directly through proxy
  console.log(proxiedCalculator.__proto__ === Calculator.prototype); // Output: true

  // Attempt to modify a property (should throw an error)
  proxiedCalculator.result = 100; // Error: Cannot modify property "result".
} catch (error) {
  console.error(error.message); // Output: Cannot modify property "result". The calculator is immutable.
}

أفضل جزء في استخدام الوكيل بهذه الطريقة هو:

  • يرث كائن الوكيل النموذج الأولي لفئة الحاسبة الأصلية.
  • يتم تجنب الطفرات من خلال فخ الوكيل.

شرح الكود

1). وراثة النموذج الأولي:

  • لا يتداخل الوكيل مع النموذج الأولي الأصلي لفئة **الآلة الحاسبة **.
  • يتم تأكيد ذلك عن طريق التحقق مما إذا كان proxiedCalculator.proto === Calculator.prototype. ستكون النتيجة صحيح.

2). التعامل مع getOperations:

  • يعترض الحصول على اعتراض الوصول إلى الخاصية على كائن الوكيل.
  • نحن نستخدم Reflect.get للوصول بأمان إلى الخصائص والأساليب من الكائن الأصلي.

3). منع الطفرات:

يلقي اعتراض المجموعة خطأً عندما تكون هناك محاولة لتعديل أي خاصية على الكائن الهدف. وهذا يضمن الثبات.

4). استخدام طرق النموذج الأولي من خلال الوكيل:

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

النقاط الرئيسية التي يجب مراعاتها هنا هي:

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

إذا وصلت إلى هذا الحد، فلا تنس الضغط على إعجاب ❤️ وإسقاط تعليق أدناه يتضمن أي أسئلة أو أفكار. تعليقاتك تعني لي كل شيء، وأود أن أسمع منك!

بيان الافراج يتم استنساخ هذه المقالة على: https://dev.to/srishtikprasad/proxy-design-patern-4mm؟1 إذا كان هناك أي انتهاك ، فيرجى الاتصال بـ [email protected] لحذفه.
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3