ما هي أفضل طريقة للتعامل مع التبعيات الدائرية بين الكائنات؟

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

  •  06-07-2019
  •  | 
  •  

سؤال

في الكود الخاص بي، لدي الكائنات التالية:

  • errormanager - يتحكم في كيفية تسجيل الأخطاء في التطبيق
  • ConfigManager - يتحكم في كيفية الحصول على معلومات التكوين

في المشروع الذي أعمل عليه، يحتاج ErrorManager إلى سحب معلومات التكوين باستخدام مثيل ConfigManager بينما يستخدم ConfigManager ErrorManager في حالة حدوث خطأ.

في الوقت الحالي، أقوم بما يلي في الكود:

ErrorManager _errorManager = new CustomErrorManager();
ConfigManager _configManager = new CustomConfigManager(_errorManager);
_errorManager.SetConfigurationManager(_configManager);

هل هناك طريقة بالنسبة لي لتنظيف هذا المرجع الدائري للتبعيات؟

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

المحلول

سأقوم بإنشاء ما يلي:

ErrorConfig _errorConfig = ...; 
// ErrorConfig is a new config object containing only ErrorManager Configuration
ErrorManager _errorManager = new CustomErrorManager(_errorConfig);
ConfigManager _configManager = new CustomConfigManager(_errorManager);

الآن، ConfigManager يمكن استخدام ErrorManager الجاهز للتشغيل دون مشكلة تمهيد حيث يمكن لـ ErrorManager ليس جاهزًا للتعامل مع الأخطاء.

نصائح أخرى

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

BootstrapConfigManager _bcm = new BootstrapConfigManager();
ErrorManager _errorManager = new CustomErrorManager(_bcm);
ConfigManager _configManager = new CustomConfigManager(_bcm, _errorManager);

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

سأقوم بإنشاء طرق ملحقة لكل منها تسمى AddRelationship، مع تمرير الكائن الآخر كمعلمة.

سيضيف الكائن الذي تم تمريره العلاقة ثم يستدعي طريقة AddRelationship للكائن الآخر:

static void AddRelationship(this ConfigManager configMgr, ErrorManager errMgr)
{
    this.ErrorManager = errMgr;
    if (this != errMgr.ConfigManager)
        errMgr.AddRelationship(this);
}

static void AddRelationship(this ErrorManager errMgr, ConfigManager configMgr)
{
    this.ConfigManager = configMgr;
    if (this != configManager.errMgr)
        configMgr.AddRelationship(this);
}

وهذا يعني أنه يمكنك إضافة العلاقة باستخدام أي من الكائنين.

ConfigManager cfg = new ConfigManager();
ErrorManager err = new ErrorManager();
//Assign using either:
err.AddRelationship(cfg);
//Or
cfg.AddRelationship(err);

يجب عليك أيضًا إنشاء ملحقات RemoveRelationship.

static void RemoveRelationship(this ConfigManager configMgr, ErrorManager errMgr)
{
    if (this.errorManager == errMgr)
    {
        this.errorManager = null;
        if (errManager.configManager == this) 
            errMgr.RemoveRelationship(this);
    }
}

static void RemoveRelationship(this ErrorManager errMgr, ConfigManager cfgMgr)
{
    if (this.ConfigManager == cfgMgr)
    {
        this.configManager = null;
        if (cfgMgr.errorManager == this)
            cfgMgr.RemoveRelationship(this);
    }
}

لا أعلم أن المراجع الدائرية هي أ خصوصًا ممارسة ترميز جيدة، ولكن هذا يجب أن يحل السؤال كما هو مطلوب.

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