【问题标题】:What's the best way to handle circular dependencies amongst objects?处理对象之间的循环依赖关系的最佳方法是什么?
【发布时间】:2010-10-24 07:03:49
【问题描述】:

在我的代码中,我有以下对象:

  • ErrorManager - 控制错误的方式 已登录应用程序
  • ConfigManager - 控制如何 获取配置信息

在我正在处理的项目中,ErrorManager 需要使用 ConfigManager 实例提取配置信息,而 ConfigManager 使用 ErrorManager 以防发生错误。

目前,我正在代码中执行以下操作:

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

有没有办法让我清理这个依赖的循环引用?

【问题讨论】:

  • 通常大量的“Manager”类表明滥用单例模式而不是正确的面向对象设计。
  • 我将单例模式用于应用程序中的特定职责(即错误管理和配置管理)。单个实例不是通过工厂模式实现的,因为我正在考虑在不久的将来可能会在应用程序中添加一个 IOC 容器来为我处理依赖关系。现在,我只专注于解决依赖关系,以便轻松添加 IoC 容器。

标签: dependency-injection dependencies


【解决方案1】:

我会创建以下内容:

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】:

    我将为每个称为 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);
        }
    }
    

    我不知道循环引用是一种特别是良好的编码习惯,但这应该可以解决所提出的问题。

    【讨论】:

    • 虽然这可以作为一种可能的解决方案,但据我所知,从 IoC 容器的角度来看,它是行不通的;但是,我仍在学习几个不同的 IoC 容器,所以我可能错了。
    • 啊,您没有在原始问题中指定,否则我可能没有发布。由于其他项目需求,我还没有时间研究 IoC 容器或依赖注入。
    【解决方案3】:

    重构您的代码。您可能可以分解类以隔离一部分,您可以先初始化并传递给这两个类。

    【讨论】:

      【解决方案4】:

      循环引用通常最好通过重构两者都依赖的第三个类来清理。例如,你可能有这样的事情:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-02
        • 1970-01-01
        • 2015-07-15
        • 2010-09-21
        相关资源
        最近更新 更多