سؤال

هل يمكن لأي شخص أن يخبرني ببعض المواقف على سبيل المثال حيث يجب استخدام النمط؟

أعطني بعض الاستخدام الحقيقي من تجربتك الخاصة.

(لقد وجدت حتى الآن أنه مفيد فقط لرسم خرائط البيانات في طبقة DA. آسف !!!)

هل كانت مفيدة؟

المحلول

حاولت أن أعطيك بعض الأمثلة في العالم الحقيقي ، وبعض المواقف الشائعة التي يجب استخدام نمط طريقة القالب.

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

    public abstract class Salary {
    
       public final void calculate() {
            System.out.println("First shared tasks is done.");
            getBaseSalary();
            System.out.println("Second shared tasks is done.");
       }
    
       public abstract void getBaseSalary();
    
    }
    
    public class Hourly extends Salary {
    
        @Override
        public void getBaseSalary() {
            System.out.println("Special Task is done.");
        }
    
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Salary salary = ....
            salary.calculate();
        }
    }
    
  • عندما تواجه العديد من نفس الخط من الرموز التي يتم تكرارها من خلال تأجيل بعض خطوات الخوارزمية الخاصة بك. عندما تقوم بتنفيذ محتوى طريقة أو وظيفة ، يمكنك العثور على قسم من الكود الخاص بك والذي يختلف من نوع إلى نوع آخر. تتمثل ميزة هذه الأقسام في أنه يمكن للمرء إعادة تعريف أو تعديل هذه الأقسام من الطريقة أو الدالة دون تغيير الهيكل الرئيسي (طريقة أو وظيفة) الخوارزمية. على سبيل المثال ، إذا كنت ترغب في حل هذه المشكلة بدون هذا النمط ، فستواجه هذا العينة:

Function0: function1: ... functionn:

1       1               1
2       2               2
...     ...             ...
5       6               n
3       3               3
4       4               4
...     ...             ...

كما ترون ، تختلف قوانين القسم 5 و 6 و N تختلف من وظيفة إلى وظيفة أخرى ، ومع ذلك يمكنك مشاركة أقسام مثل 1،2،3،4 التي يتم تكرارها. دعنا ننظر في حل مع واحدة من مكتبات Java الشهيرة.

public abstract class InputStream implements Closeable {

    public abstract int read() throws IOException;

    public int read(byte b[], int off, int len) throws IOException {
        ....

        int c = read();
        ....
    }

    ....

}

public class ByteArrayInputStream extends InputStream {  

    ...

    public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
        }
    ...
}
  • عندما تكون مصممًا لإطار عمل ، تريد أن يستخدم عملائك فقط أي رمز قابل للتنفيذ يتم تمريره كوسيطة لإطارك ، والذي من المتوقع أن يعادوه (تنفيذ) تلك الوسيطة في وقت معين. قد يكون هذا التنفيذ فوريًا كما هو الحال في رد اتصال متزامن ، أو قد يحدث في وقت لاحق كما هو الحال في رد اتصال غير متزامن. دعنا ننظر في واحدة من الشهيرة.

    public abstract class HttpServlet extends GenericServlet 
        implements java.io.Serializable  {
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
            ...
        }
    
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
            ....
            doGet(req, resp);
            ...
        }
        ...
    }
    }
    
    public class MyServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    
                //do something
            ...
        }
        ...
    }
    

نصائح أخرى

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

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

أمثلة:

  • java.util.abstractlist
  • أساليب Servlet's Doget و Dopost
  • طريقة onMessage الخاصة بـ MDB
  • فئة العمل الدعامات
  • فئات الوصول إلى بيانات الربيع

السلبيات: يقيدك على ميراث واحد في جافا.

تطبيق طريقة القالب النمط له خصائصان رئيسيتان:

  1. هناك فئة قاعدة (في جافا ، واحدة فقط مع protected المُنشئون وأعلنوا اختياريًا باسم abstract) والتي سيتم فئاتها في رمز العميل.
  2. هناك مجموعتان من الأساليب محدد في الفئة الأساسية: أ) واحد أو أكثر طرق القالب (عادة واحد فقط) وواحد أو أكثر العملية البدائية الطرق (عادة أكثر من واحد). تمثل كل طريقة قالب عملية عالية المستوى ، يتم تنفيذها في الفئة الأساسية نفسها من حيث العمليات البدائية ، والتي من المفترض تنفيذها/تجاوزها في كل فئة فرعية محددة. عادةً ما تكون طريقة القالب عامة وغير قابلة للإلغاء (final, ، في جافا) ؛ يجب أن تحدد وثائق API الخاصة بها على وجه التحديد طرق التشغيل البدائية التي تسميها ، ومتى (أي ، يجب أن تصف "الخوارزمية"). يجب أن تكون طريقة التشغيل البدائية ، والتي تمثل خطوة في الخوارزمية ، غير عامة ولكنها قابلة للتطبيق (protected, ، في جافا) ، ويمكن أن يكون من نوعين: أ) طريقة مجردة يجب يتم تنفيذها في الفئة الفرعية ؛ ب) طريقة ذات تطبيق افتراضي/فارغ مايو يتم تجاوزها في الفئة الفرعية.

مثال جيد في Java 6 SDK هو execute() طريقة javax.swing.SwingWorker الفصل (إنه ملف public final void طريقة). في هذه الحالة ، طرق التشغيل البدائية doInBackground(), process(List), ، و done(). أول واحد مجردة وبالتالي يتطلب تنفيذًا في الفئة الفرعية ؛ يطلق عليه طريقة القالب في موضوع خلفية. الاثنان الآخران لهما تطبيقات فارغة ويمكن أن يتم تجاوزهما اختياريًا في الفئة الفرعية ؛ يتم استدعاؤها أثناء وفي نهاية المعالجة ، على التوالي ، في مؤشر ترتيب الحدث Swing (مؤشر ترابط الأحداث) ، للسماح بالتحديثات إلى واجهة المستخدم.

في تجربتي الخاصة ، استخدمت هذا النمط أحيانًا. إحدى هذه الحالات كانت فئة قاعدة جافا تنفذ java.util.Iterator واجهة ، حيث next() هل كانت طريقة القالب ولم يكن هناك سوى طريقة عملية بدائية واحدة مسؤولة عن إنشاء فئة كيان مجال محددة (كان من المفترض أن يتم استخدامها عند التكرار على قائمة كائنات كيان المجال الثابتة ، باستخدام JDBC). مثال أفضل في نفس التطبيق كان فئة أساسية حيث نفذت طريقة القالب خوارزمية متعددة الخطوات تهدف إلى ملء "شاشة صيانة كيان العمل" (باستخدام التأرجح) من قائمة معينة من الكيانات الثابتة ؛ تم استدعاء طرق العمليات البدائية إلى 1) قم بمسح حالة الشاشة الحالية ، و 2) إضافة كيان في طريقة عرض جدول داخل الشاشة ؛ اختياريا ، تم استدعاء العمليات البدائية الأخرى من طريقة القالب إذا كانت الشاشة قابلة للتحرير.

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

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

تقدمت بطلب في أحد برنامج توليد المستندات.

public abstract DocumentGenerator() 
{
   generateHeader();
   generateBody();
   generateDetails();
}
public HTMLDocGenerator : DocumentGenerator()
{
   public override generateBody()
   {
     //generate as in html format
   }
}

يمكنك الحصول على تطبيق مختلف مثل مولد CSV PDF والقيمة هنا هي أنها comform إلى الخوارزمية (إنشاء -> رأس ، الجسم ، التفاصيل).

يجب استخدام نمط القالب عندما يكون هناك خوارزمية مع العديد من التطبيقات. يتم تعريف الخوارزمية في وظيفة في فئة قاعدة ويتم التنفيذ بواسطة فئة الأساس والفئات الفرعية. يتم تقديم تفسير مفصل مع مثال في الوقت الفعلي في http://preciselyconcise.com/design_patterns/templatemethod.php

سأرسم مثالًا حقيقيًا في العالم الحقيقي حيث استخدمت بعض أساليب القالب.

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

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

أعتقد أن هذا النوع من حالات الاستخدام قد نشأت مما أطلق عليه ثقب في الوسط مشكلة.

لقد استخدمت طريقة القالب لمنطق العمل حيث شارك عدد من المكونات نفس العملية ولكن التنفيذ كان مختلفًا قليلاً.

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top