سؤال

لنفترض أن لدى الأنواع التالية من البيانات:

class Customer {
  String id; // unique
  OtherCustData someOtherData;
}

class Service {
  String url; // unique
  OtherServiceData someOtherData;
}

class LastConnection {
  Date date;
  OtherConnData someOtherData; // like request or response
}

الآن أنا بحاجة إلى أن نتذكر عند كل العملاء متصلة مع بعضها من الخدمات.
وأود أن جعل هيكل:

Map<Customer, Map<Service, LastConnection>> lastConnections;

أو أن تكون قادرة على البحث عن طريق معرفات وليس لديك لكتابة كل تساوي() و hashCode():

Map<String, Map<String, LastConnection>> lastConnections;

الآن أنا يمكن الوصول إلى LastConnection البيانات

LastConnection connection = lastConnections.get(custId).get(srvUrl);

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

class CustomerConnections extends HashMap<String, LastConnection> {
}

class AllConnections extends HashMap<String, CustomerConnections> {
    public LastConnection get(String custId, String srvUrl) {
        return get(custId).get(srvUrl);
    }
}

حسنا, لقد تعلمت بالفعل أن الميراث هو 3v1l ، لذلك دعونا نحاول تكوين:

class CustomerConnections {
    Map<String, LastConnection> customerConnections;
    LastConnection get(String srvUrl) { 
        return customerConnections.get(srvUrl);
    }
    ... // all other needed operations;
}

class AllConnections {
    Map<String, CustomerConnections> allConnections;
    public LastConnection get(String custId, String srvUrl) {
        return get(custId).get(srvUrl);
    }
    public CustomerConnection get(String custId) {
        return allConnections.get(custId);
    }
    ... // all other needed operations;
}

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

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

المحلول

<اقتباس فقرة>   

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

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

<اقتباس فقرة>   

ولكن من شأنها أن تجعل قانون بلدي أكثر وضوحا

وهذا شيء عظيم وهو سبب وجيه للقيام بذلك. YourClass.getCustomerConnection (CID) هو أكثر وضوحا من yourCollection.get (معرف). احصل على (معرف) .getConnection (). تحتاج إلى جعل حياة الأشخاص الذين يستخدمون هذا الرمز أسهل، حتى لو كنت هذا الشخص.

<اقتباس فقرة>   

و(خصوصا عندما تكون هناك مستويات المقبلة - مثل خريطة AllConnections حسب الشهر وهلم جرا)

وجيد، فأنت التخطيط للمستقبل، وجعل للمد التعليمات البرمجية. وهي ممارسة OO جيدة. في رأيي conculsion كنت قد وصلت لوحدك هو ما أود القيام به.

نصائح أخرى

وأود أن إنشاء كائن مخصص لتخزين هذه المعلومات.ما كنت خلق هو مدير كائن بدلا من مجرد جمع.

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

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

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

أعتقد أن عليك أن تنظر أيضا في كيفية مجموعات تنوي استخدامها وكيف يتم الحصول على البيانات:

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

كيف يمكنك الحصول على قائمة البيانات الخاصة بك ؟ إذا تم تخزينها في قاعدة البيانات, ثم ربما يمكنك استخدام SQL لتحديد LastConnections من قبل العميل و/أو الخدمات و/أو الشهر, بدلا من الاضطرار إلى الحفاظ على datastructures نفسك (فقط عودة بسيطة قوائم أو خرائط اتصالات أو تهم اتصالات).أو ربما كنت لا ترغب في تشغيل استعلام عن كل طلب حتى لا تحتاج إلى الحفاظ على كل datastructure في الذاكرة.

التغليف عموما هو شيء جيد على الرغم من, لا سيما وأنها يمكن أن تساعدك على التمسك القانون ديميتر ربما يمكنك دفع بعض العمليات التي سوف تؤدي على مجموعات العودة إلى AllConnections فئة (الذي هو فعليا DAO).وهذا يمكن أن تساعد في كثير من الأحيان اختبار وحدة.

أيضا, لماذا تمديد HashMap يعتبر الشر هنا ، معتبرا أن كنت فقط ترغب في إضافة تافهة مساعد الأسلوب ؟ في التعليمات البرمجية الخاصة بك على AllConnections, AllConnections دائما تتصرف بنفس الطريقة كما HashMap - هو polymorphically للاستبدال.بالطبع, كنت يحتمل قفل نفسك في استخدام HashMap (بدلا من TreeMap ، إلخ) ، ولكن هذا ربما لا يهم لأنه لديه نفس العام الأساليب الخريطة.ومع ذلك ، إذا كنت فعلا تريد أن تفعل هذا حقا لا يعتمد على كيفية كنت تنوي استخدام مجموعات - أنا فقط لا أعتقد أنه يجب تلقائيا خصم تنفيذ الميراث كما دائما سيئة (انها مجرد عادة!)

class AllConnections extends HashMap<String, CustomerConnections> {
    public LastConnection get(String custId, String srvUrl) {
        return get(custId).get(srvUrl);
    }
}

لماذا لا تستخدم custId+"#"+srvurl كمفتاح في Map<String, LastConnection> بسيطة؟

وأو استخدام الصفوف (tuple) أو الطبقة زوج كمفتاح الذي يحتوي على هويات اثنين وتنفيذ hashCode() وequals() - و" أنظف "حل OO.

لماذا الحفاظ على العلاقات بين الكائنات خارج تلك الكائنات.

وأنا أقترح شيء كما يلي:

public class Customer 
{
  public List<LastConnection> getConnectionHistory() 
  {
    ... 
  }

  public List<LastConnection> getConnectionHistory(Service service) 
  {
    ...
  }

  public List<LastConnection> getConnectionHistory(Date since) 
  {
    ...
  }
}

public class LastConnection
{
  public Date getConnectionTime() 
  {
    ...
  }

  public Service getService()
  {
    ...
  }
}

وأنت ثم تمرير List<Customer> إلى الأساليب التي تستخدم هذه المعلومات.

يمكنك إنشاء فئة تنفذ Map<K,V>, و داخليا مندوب وعاء الخريطة:

class CustomerConnections implements Map<String,LastConnection> {
    private Map<String, LastConnection> customerConnections;

    @Override
    public LastConnection get(Object srvUrl) { 
        return customerConnections.get(srvUrl);
    }
    // all other needed operations;
}

الشيء الجميل مع هذا النهج هو أنه يمكنك تمرير جميع أنحاء Map والتي لديها معيار واضح المعالم العقد ، ولكن يمكنك تجنب توسيع مكتبة دروس, الذي غالبا ما يكون مكروها.

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

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