Каков наилучший способ обработки циклических зависимостей среди объектов? - PullRequest
6 голосов
/ 06 мая 2009

В моем коде у меня есть следующие объекты:

  • ErrorManager - контролирует, как ошибки залогинены в приложении
  • ConfigManager - контролирует, как информация о конфигурации получается

В проекте, над которым я работаю, ErrorManager должен получать информацию о конфигурации с помощью экземпляра ConfigManager, в то время как ConfigManager использует ErrorManager в случае возникновения ошибки.

В данный момент я делаю следующее в коде:

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

Есть ли способ для меня, чтобы очистить эту циклическую ссылку зависимостей?

Ответы [ 4 ]

3 голосов
/ 06 мая 2009

Я бы создал следующее:

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 не готов к обработке ошибок.

2 голосов
/ 06 мая 2009

Циркулярные ссылки обычно лучше очищать путем рефакторинга третьего класса, от которого зависят оба. Например, у вас может быть что-то вроде этого:

BootstrapConfigManager _bcm = new BootstrapConfigManager();
ErrorManager _errorManager = new CustomErrorManager(_bcm);
ConfigManager _configManager = new CustomConfigManager(_bcm, _errorManager);
0 голосов
/ 06 мая 2009

Я бы создал методы расширения для каждого вызываемого 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);
    }
}

Я не знаю, что циклические ссылки являются особенно хорошей практикой кодирования, но это должно решить вопрос в том виде, в котором он был задан.

0 голосов
/ 06 мая 2009

Рефакторинг вашего кода. Вероятно, вы можете разбить классы, чтобы изолировать часть, которую вы можете инициализировать первой и передать обоим классам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...