了解使用基于接口的工厂与普通IoC接口实例化之间的区别

时间:2014-10-26 22:16:37

标签: .net inversion-of-control castle-windsor factory-pattern windsor-facilities

首先,对不起,如果我对条款的使用无效,试图做到正确但不确定是否正确,这对我来说有点困惑。

我正在使用Windsor并且无法确定何时以及如何(我认为)使用基于接口的工厂进行实例化而不总是正常的ctor(IObj obj)

让我举个例子。我有这个构造函数

private ICache _cache;
private ICache _cache2;
public HomeController(ICacheFactory cacheFactory, ICache cache)
{
    this._cache = cacheFactory.Create<ICacheFactory>();
    this._cache2 = cache;
}

我设置代码的方式_cache_cache2返回exakt相同的对象。为什么我应该使用ICacheFactory方法来实现一个类?

这是我配置它的方式

public interface ICacheFactory
{
    ICache Create<T>();
}

public interface ICache
{
    bool Get<T>(string key, out T exists);
}

public bool Get<T>(string key, out T result)
    {
        // my code
    }

public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());
        container.AddFacility<TypedFactoryFacility>();
        container.Register(Component.For<ICacheFactory>().AsFactory());

        container.Register(Component.For<ICache>().ImplementedBy<CacheFactory>().LifestyleTransient());
    }

我正在考虑将CacheFactory视为

public class CacheFactory : ICache
{
    private static ICache cacheObject;
    public static ICache Current
    {
        get
        {
            if (cacheObject == null)
                cacheObject = new CacheFactory();

            return cacheObject;
        }
    }

    public bool Get<T>(string key, out T result)
    {
        // my code
    }
}

因此,我是在思考interface-based factories做什么,如果不是为什么我应该使用ICacheFactory方式来实现一个阶级的方式?

(我应该清楚我已经阅读了Windsor文档但没有100%获得它。)

感谢您的时间,我希望不要模糊。

1 个答案:

答案 0 :(得分:3)

正确应用依赖注入时,您会发现这将大大减少您需要使用的工厂数量。工厂仍然有用,有时需要,但它们的使用仅限于你要么:

  1. 明确需要控制服务的生命周期(例如,因为你需要在方法的末尾处理这样的实例)。
  2. 当你需要通过推迟创作来打破对象图时。
  3. 在大多数其他情况下,不应使用工厂。特别是在您正在显示的情况下,在构造函数内部调用工厂。这没用,因为:

    1. 你没有推迟构建对象图,因为从构造函数内部调用工厂与调用构造函数之前调用工厂具有相同的效果。
    2. 您的代码库变得复杂,因为您的HomeController现在依赖于额外的抽象ICacheFactory,而它只需依靠ICache即可满足其需求。这也使测试复杂化。为什么HomeController根本需要知道这个工厂?
    3. 此外,您声明“_cache和_cache2返回完全相同的对象”,因此无需在此处注入两个缓存。所以你的构造函数应该是:

      private ICache _cache;
      public HomeController(ICache cache)
      {
          this._cache = cache;
      }
      

      如果您的工厂包含进行选择的复杂行为,您仍然可以在Composition Root中使用它,但可能没有理由让应用程序代码依赖它。