يجب أن لا فرعية حسب نوع الكائن إذا كان هناك العديد من أنواع ؟

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

سؤال

أنا أعمل مع سجل الأحداث حيث هناك حوالي 60 المختلفة "أنواع" من الأحداث.كل حدث أسهم حوالي 10 خصائص ثم هناك فئات فرعية من الأحداث التي تشترك في مختلف الخصائص الإضافية.

كيف نتعامل مع هذه الأحداث لا تعتمد على نوع أو ما الفئوية واجهات تنفيذها.

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

هو أكثر ملاءمة لاستخدام واحد فئة الحدث مع "نوع" ملك وكتابة المنطق أن يتحقق نوع والحفاظ على منظمة فئات من أنواع (مثلا ، قائمة أنواع الأحداث التي هي فئة a ، القائمة الثانية من الفئة ب ، إلخ) ؟ أو هو فئة فرعية التصميم الأنسب في هذه الحالة ؟

النهج الأول:

public interface Category1 {}
public interface Category2 {}

public abstract class Event {
 private base properties...;
}

public class EventType1 extends Event implements Category1, Category2 {
 private extra properties ...;
}

public class EventType2 extends Event implements Category3, Category4 {
 private extra properties ...;
}

النهج الثاني:

public enum EventType {TYPE1, TYPE2, TYPE3, ...}
public class Event {
 private union of all possible properties;
 private EventType type;
}

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

أنا بحاجة إلى التعليمات البرمجية التي يقوم بأمور مثل:

if(event instanceof Category1) {
  ...
}

هذا يعمل بشكل جيد في النهج الأول في أنه بدلا من instanceof أنا يمكن فقط استدعاء الأسلوب على الحدث وتنفيذ "نفس القانون" في كل مناسبة فرعية.

ولكن النهج الثاني هو الكثير أكثر إيجازا.ثم أكتب أشياء مثل:

if(CATEGORY1_TYPES.contains(event.getEventType()) {
 ...
}

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

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

المحلول

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

هل هذا الحدث الخاص بك الأشياء تحتاج الأساليب التي تتصرف بشكل مختلف لكل نوع ؟ إذا كان الأمر كذلك ، استخدام الميراث.

إن لم يكن, استخدام التعداد لتصنيف نوع الحدث.

نصائح أخرى

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

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

حتى هنا هو النهج المقترح:على افتراض كنت في حاجة إلى نفسه تنفيذ لفئة معينة واجهة الأسلوب (بغض النظر عن الحدث), هل يمكن كتابة تنفيذ الدرجة لكل فئة واجهة.

لذلك سيكون لديك:

public class Category1Impl implements Category1 {
    ...
}

public class Category2Impl implements Category2 {
    ...
}

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

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

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

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

مع هذا التغيير, كنت قادرا على حذف حوالي 100 عملاقة فئات رمز إنجاز الكثير من نفس المنطق في حوالي 10 أسطر من التعليمات البرمجية في فئة واحدة.

الدرس(s) تعلمت:ليس من الحكمة دائما أن تطبيق OO نماذج نموذج البيانات.لا تركز على توفير مثالي نموذج البيانات عبر OO عند العمل مع عدد كبير من المتغير المجال.OO فوائد تصميم وحدة تحكم أكثر من نموذج في بعض الأحيان.لا تركز على التحسين مقدما لأن عادة 10% فقدان الأداء مقبولة و يمكن استعاد عبر وسائل أخرى.

في الأساس كنت أكثر الهندسية المشكلة.اتضح أن هذا هو حال السليم OO التصميم هو مبالغة ويتحول ليلة واحدة المشروع في شهر 3 المشروع.بالطبع, يجب أن تعلم الأشياء بالطريقة الصعبة!

مجرد وجود عدد كبير من .ملفات جافا ليست بالضرورة سيئة.إذا كنت يمكن أن مجد استخراج عدد صغير (2-4 أو نحو ذلك) من الواجهات التي تمثل عقود من الفئات ، ثم حزمة جميع تطبيقات ، API أنت الحاضر يمكن أن تكون نظيفة جدا حتى مع 60 تطبيقات.

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

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

ربما شيء مثل هذا ؟

class EventType {

  protected EventPropertyHandler handler;

  public EventType(EventPropertyHandler h) {
     handler = h;
  }

  void handleEvent(map<String,String> properties) {
    handler.handle(properties);
  }
}

abstract class EventPropertyHandler {
   abstract void handle(map<String, String> properties);
}
class SomeHandler extends EventPropertyHandler {
   void handle(map<String, String> properties) {
      String value = properties.get("somekey");
      // do something with value..
   }
}

class EventBuilder {
   public static EventType buildSomeEventType() {
      // 
      EventType e = new EventType( new SomeHandler() );
   }
}

ربما يكون هناك بعض التحسينات التي يمكن إدخالها ، ولكن قد الحصول على انك بدأته.

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