الفرق بين المراجعتين لصفحة: «Design Patterns/facade»

من موسوعة حسوب
1.0: عنوان الصفحة
 
2.0 محتوى
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:نمط الواجهة}}</noinclude>
<noinclude>{{DISPLAYTITLE:نمط الواجهة}}</noinclude>
نمط الواجهة هو نمط تصميم هيكلي يوفر واجهة مبسطة لمكتبة ما أو إطار عمل أو أي تركيبة معقدة من الفئات.
== المشكلة ==
تخيل أن عليك جعل شيفرتك تعمل مع نطاق واسع من الكائنات التي تنتمي إلى مكتبة معقدة أو إطار عمل معقد، فالمعتاد أنك ستحتاج إلى بدء كل تلك الكائنات وتتابع الاعتماديات وتنفذ الأساليب بالترتيب الصحيح، وهكذا. ونتيجة لهذا يكون المنطق التجاري لفئاتك (Business Logic) مرتبطًا بشدة بتفاصيل الاستخدام لفئات الطرف الثالث، مما يجعل من الصعب عليك إدراكه وصيانته.
== الحل ==
ويأتي نمط الواجهة (Facade) هنا كفئة توفر واجهة بسيطة لنظام فرعي معقد يحتوي الكثير من الأجزاء المتحركة، وقد يكون ما يقدمه نمط الواجهة محدودًا مقارنة بالعمل مع النظام الفرعي مباشرة، لكنها ستحتوي  فقط على المزايا التي يرغب فيها العملاء.
سيكون نمط الواجهة مفيدًا أيضًا عندما تحتاج إلى تكامل تطبيقك مع مكتبة معقدة بها عشرات المزايا، لكنك لا تريد إلا جزءًا صغيرًا من وظائفها. فقد يستخدم تطبيق يرفع مقاطع مضحكة للقطط إلى الشبكات الاجتماعية مكتبة تحويل فيديو احترافية، لكنه لا يحتاج حقيقة إلا إلى فئة مع أسلوب <code>(encode(filename, format</code> وحيد، وبعد إنشاء هذه الفئة وتوصيلها بمكتبة تحويل الفيديو، تكون بهذا قد صنعت أول واجهة لك.
== مثال واقعي ==
ضع الصورة. طلب المنتجات عن طريق الهاتف.
حين تتصل بمتجر لتطلب منتجًا ما، فإن الموظف على الطرف الأخر هو واجهتك التي تتصل من خلالها بالخدمات والأقسام داخل المتجر، بدلًا من التعامل مع المتجر مباشرة، وما يقدمه لك الموظف هو واجهة صوتية بسيطة لنظام الطلبات وطرق الدفع وخدمات التوصيل المختلفة.
== البُنية ==
# توفر الواجهة وصولًا سهلًا إلى جزء معين من وظائف النظام الفرعي، وهو يعرف إلى أين يوجِّه طلب العميل وكيف يدير كل الأجزاء المتحركة.
# يمكن إنشاء فئة واجهة إضافية لمنع تلويث واجهة ما بمزايا خارج نطاق وظيفتها تجعلها نظامًا فرعيًا معقدًا لا يختلف عن النظام الذي أنشئت من أجل تبسيطه، ويمكن استخدام الواجهات الإضافية من قبل العملاء والواجهات الأخرى على حد سواء.
# يتكون النظام المعقد من عشرات الكائنات المختلفة، وعليك أن تتعمق في تفاصيل استخدام النظام الفرعي من أجل جعلهم جميعًا ينفذون شيئًا مفيدًا. هذه التفاصيل قد تكون بدء الكائنات بالترتيب الصحيح، وتزويدها بالبيانات في صيغ مناسبة. ولا تكون فئات النظام الفرعي مدركة لوجود الواجهة، فهي تعمل داخل النظام وتتعامل مع بعضها مباشرة.
# يستخدم العميل الواجهة بدلًا من استدعاء كائنات النظام الفرعي مباشرة.
== مثال توضيحي ==
في هذا المثال، يبسط نمط الواجهة التفاعل مع إطار عمل معقد لتحويل الفيديو.
ضع الصورة. مثال لعزل عدة اعتماديات داخل فئة واجهة وحيدة.
بدلًا من جعل شيفرتك تعمل مع العشرات من فئات إطار العمل مباشرة، فإنك تنشئ فئة واجهة تحتوي هذه الوظيفة وتخفيها من  بقية الشيفرة، وهذه البنية تساعدك أيضًا على تقليل الجهد اللازم للترقية إلى نسخ مستقبلية من إطار العمل أو استبداله بغيره، والشيء الوحيد الذي ستحتاج إلى تغييره في تطبيقك هو الاستخدام لأساليب الواجهة.<syntaxhighlight lang="java">
// هذه بعض من فئات لإطار عمل من طرف ثالث معقد لتحويل الفيديو.
// نحن لا نتحكم في هذه الشيفرة، ولهذا لا نستطيع تبسيطها.
class VideoFile
// ...
class OggCompressionCodec
// ...
class MPEG4CompressionCodec
// ...
class CodecFactory
// ...
class BitrateReader
// ...
class AudioMixer
// ...
// سننشئ فئة واجهة تخفي تعقيد إطار العمل خلف واجهة بسيطة.
// هذه مقايضة بين الوظيفة والبساطة.
class VideoConverter is
    method convert(filename, format):File is
        file = new VideoFile(filename)
        sourceCodec = new CodecFactory.extract(file)
        if (format == "mp4")
            destinationCodec = new MPEG4CompressionCodec()
        else
            destinationCodec = new OggCompressionCodec()
        buffer = BitrateReader.read(filename, sourceCodec)
        result = BitrateReader.convert(buffer, destinationCodec)
        result = (new AudioMixer()).fix(result)
        return new File(result)
// لا تعتمد فئات التطبيق على ملايين الفئات التي يوفرها إطار العمل المعقد.
// وكذلك، فإن قررت تبديل أطر العمل فلا تحتاج إلا إلى كتابة فئة الواجهة فقط.
class Application is
    method main() is
        convertor = new VideoConverter()
        mp4 = convertor.convert("youtubevideo.ogg", "mp4")
        mp4.save()
</syntaxhighlight>
== قابلية التطبيق ==

مراجعة 04:20، 12 مارس 2019

نمط الواجهة هو نمط تصميم هيكلي يوفر واجهة مبسطة لمكتبة ما أو إطار عمل أو أي تركيبة معقدة من الفئات.

المشكلة

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

الحل

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

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

مثال واقعي

ضع الصورة. طلب المنتجات عن طريق الهاتف.

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

البُنية

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

مثال توضيحي

في هذا المثال، يبسط نمط الواجهة التفاعل مع إطار عمل معقد لتحويل الفيديو.

ضع الصورة. مثال لعزل عدة اعتماديات داخل فئة واجهة وحيدة.

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

// هذه بعض من فئات لإطار عمل من طرف ثالث معقد لتحويل الفيديو.
// نحن لا نتحكم في هذه الشيفرة، ولهذا لا نستطيع تبسيطها.

class VideoFile
// ...

class OggCompressionCodec
// ...

class MPEG4CompressionCodec
// ...

class CodecFactory
// ...

class BitrateReader
// ...

class AudioMixer
// ...


// سننشئ فئة واجهة تخفي تعقيد إطار العمل خلف واجهة بسيطة. 
// هذه مقايضة بين الوظيفة والبساطة.
class VideoConverter is
    method convert(filename, format):File is
        file = new VideoFile(filename)
        sourceCodec = new CodecFactory.extract(file)
        if (format == "mp4")
            destinationCodec = new MPEG4CompressionCodec()
        else
            destinationCodec = new OggCompressionCodec()
        buffer = BitrateReader.read(filename, sourceCodec)
        result = BitrateReader.convert(buffer, destinationCodec)
        result = (new AudioMixer()).fix(result)
        return new File(result)

// لا تعتمد فئات التطبيق على ملايين الفئات التي يوفرها إطار العمل المعقد.
// وكذلك، فإن قررت تبديل أطر العمل فلا تحتاج إلا إلى كتابة فئة الواجهة فقط.
class Application is
    method main() is
        convertor = new VideoConverter()
        mp4 = convertor.convert("youtubevideo.ogg", "mp4")
        mp4.save()

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