依赖倒置。 对象创建

根据SOLID原则,类不能依赖其他类,必须注入依赖关系。 这很简单:

class Foo
{
    public Foo(IBar bar)
    {
        this.bar = bar;
    }

    private IBar bar;
}

interface IBar 
{
}

class Bar: IBar 
{
}

但是如果我想让我的Foo类能够创建Bar,不知道IBar背后的具体实现是什么? 我可以在这里想到4个解决方案,但它们都有缺点:

  • 注入物体的类型并使用反射
  • 使用泛型
  • 使用“服务定位器”并调用Resolve()方法。
  • 创建一个单独的工厂类并将其注入到Foo中:

  • class Foo
    {
        public void DoSmth(IBarCreator barCreator) 
        {
            var newBar = barCreator.CreateBar();
        }
    }
    
    interface IBarCreator 
    {
        IBar CreateBar();
    }
    
    class BarCreator : IBarCreator
    {
        public IBar CreateBar()
        {
            return new Bar();
        }
    }
    

    最后一种情况看起来很自然,但BarCreator类的代码太多了。 那么你怎么看,哪个最好?


    在这种情况下,我喜欢“注入” Func<IBar> 。 像这样:

    class Foo
    {
        public Foo(Func<IBar> barCreator)
        {
            this.bar = barCreator();
        }
    
        private IBar bar;
    }
    
    interface IBar 
    {
    }
    

    这是工厂制造的。

    如果你觉得你的工厂的代码太少,问问你自己有什么好处,而不是直接创建实例。 如果这些好处超过了添加的代码的成本,那么请不要担心。

    我会亲自避免服务地点,或者如果您真的必须使用它,我会将它隐藏在工厂后面。 服务地点往往容易被滥用,并可能导致您的容器找到它应该没有任何关系的代码。

    为方便起见,某些容器允许您指定一个工厂,以便在创建组件实例时由容器使用该工厂。 在这种情况下,你的类可以直接依赖IBar ,但是当你需要一个新的实例时你的容器会调用IBarCreator 。 例如,温莎城堡在其API中具有方法UseFactoryUseFactoryMethod


    这一切都取决于你的确切场景和你的需求。
    正如你所说,我认为最常用的方法就是工厂。
    如果您使用的是IoC框架(例如Ninject,Sprint.Net,Castle Windsor等,请参阅此处),服务定位器也是一个可行的解决方案。

    链接地址: http://www.djcxy.com/p/82129.html

    上一篇: Dependency inversion. Object creation

    下一篇: Use of BAL in 3 tier architecture?How to call methods from DAL to BAL