C #: فئة قاعدة استراتيجية مجردة بمثابة مصنع مجردة لكائنات الإستراتيجية

StackOverflow https://stackoverflow.com/questions/2002716

سؤال

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

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

DetailFinder DetailHandler;
if (ReportType == "Planning")
  DetailHandler = new PlanningFinder();
else if (ReportType == "Operations")
  DetailHandler = new OperationsFinder();
else if (ReportType == "Maintenance")
  DetailHandler = new MaintenanceFinder();
DataTable ChildTable = DetailHandler.FetchChildData(Master);

حيث التخطيط، العمليات، وصيانة الصيانة هي جميع الفئات الفرعية من DetailFinder.

لقد طلب مني إضافة دعم لمنطقة عمل أخرى وستكره ذلك if كتلة الاتجاه. ما سأفضله هو الحصول على طريقة تحليل من شأنها أن تبدو وكأنها هذه:

DetailFinder DetailHandler = DetailFinder.Parse(ReportType);

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

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

المحلول

قد ترغب في استخدام خريطة لأنواع طرق إنشاء:

public class  DetailFinder
{
    private static Dictionary<string,Func<DetailFinder>> Creators;

    static DetailFinder()
    {
         Creators = new Dictionary<string,Func<DetailFinder>>();
         Creators.Add( "Planning", CreatePlanningFinder );
         Creators.Add( "Operations", CreateOperationsFinder );
         ...
    }

    public static DetailFinder Create( string type )
    {
         return Creators[type].Invoke();
    }

    private static DetailFinder CreatePlanningFinder()
    {
        return new PlanningFinder();
    }

    private static DetailFinder CreateOperationsFinder()
    {
        return new OperationsFinder();
    }

    ...

}

تستعمل ك:

DetailFinder detailHandler = DetailFinder.Create( ReportType );

لست متأكدا من أن هذا أفضل بكثير من بيانك، لكنه يجعله يسهل بشكل تافه لكل من القراءة والتمديد. ما عليك سوى إضافة طريقة إنشاء وإدخال في Creators خريطة.

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

public class DetailFinder
{
      private static Dictionary<string,Type> Creators;

      static DetailFinder()
      {
           Creators = new Dictionary<string,Type>();
           Creators.Add( "Planning", typeof(PlanningFinder) );
           ...
      }

      public static DetailFinder Create( string type )
      {
           Type t = Creators[type];
           return Activator.CreateInstance(t) as DetailFinder;
      }
}

نصائح أخرى

يمكنك استخدام حاوية IOC، يتيح لك الكثير منهم تسجيل خدمات متعددة بأسماء أو سياسات مختلفة.

على سبيل المثال، مع حاوية IOC الافتراضية يمكنك القيام بذلك:

IoC.Register<DetailHandler, PlanningFinder>("Planning");
IoC.Register<DetailHandler, OperationsFinder>("Operations");
...

وثم:

DetailHandler handler = IoC.Resolve<DetailHandler>("Planning");

بعض الاختلافات في هذا الموضوع.

يمكنك إلقاء نظرة على تطبيقات IOC التالية:

طالما الكبير if كتلة أو switch بيان أو أيا كان يظهر في مكان واحد فقط، فإنه ليس سيئا للصيانة، لذلك لا تقلق بشأن ذلك لهذا السبب.

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

ومع ذلك، لست متأكدا من أن هذا هو مقدار القابلية للتمويل الذي تحتاجه حقا.

لتجنب النمو بشكل متزايد إذا تمكنت من التبديل، يمكنك تبديله جولة حتى يقوم الباحثون الزائدين بتسجيل النوع الذي يتعاملون مع فئة المصنع.

سيحتاج فئة المصنع على التهوية إلى اكتشاف جميع الباحثين المحتملين وتخزينها في Hashmap (قاموس). يمكن القيام بذلك عن طريق الانعكاس و / أو استخدام إطار التسعة المدار كما يوحي مارك Seemann.

ومع ذلك - كن حذرا من جعل هذا المعقدة مفرطة. تفضل القيام بأبسط شيء قد يعمل الآن بمنظر للصدفة عند الحاجة إليها. لا تذهب وبناء إطار معقد تكوينه الذاتي إذا كنت ستحتاج فقط إلى نوع واحد مكتشف؛)

يمكنك استخدام الانعكاس. يوجد رمز عينة لطريقة تحليل Detailfinder (تذكر إضافة خطأ في التحقق إلى هذا الرمز):

public DetailFinder Parse(ReportType reportType)
{
    string detailFinderClassName = GetDetailFinderClassNameByReportType(reportType);
    return Activator.CreateInstance(Type.GetType(detailFinderClassName)) as DetailFinder;
}

طريقة GetDetailFinderClassNameByReportType يمكن الحصول على اسم الفصل من قاعدة بيانات، من ملف التكوين إلخ.

أعتقد أن معلومات "البرنامج المساعد" ستكون مفيدة في قضيتك: ص من EAA: البرنامج المساعد

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

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

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