注入工厂会隐藏依赖吗?

时间:2016-10-07 13:36:44

标签: design-patterns dependency-injection language-agnostic factory

班级A有一个字段factory,可生成产品B。使用依赖注入注入factory。注入factory是否隐藏了类A对类Product的依赖关系?

提出这个问题的目的:在编码时,我做了一些代码,就像示例代码一样,我不知道它是不是很好的设计。我认为隐藏依赖可能是一个糟糕的设计。

示例代码:

class A
{
    private Factory factory;

    public A(Factory factory)
    {
        this.factory=factory;
    }

    public Product getProduct()
    {
        return factory.produce();
    }

    public void doSomething()
    {
        Product B = getProduct();
        // use Product to do something
    }

}

2 个答案:

答案 0 :(得分:0)

不,从Product获取Factory并不会隐藏依赖项。 A定义getProduct,返回Product,因此A取决于Product

即使您内联getProductA也会依赖于FactoryProduct依赖于A,而Product也会依赖Product

ProductProductImpl分离的正常方法是将类Product分隔为接口A和类B(或其他) ,并且在不知道实现类的情况下使用依赖注入或工厂(两者同时通常都是矫枉过正)来获取b的实例。然后 <%= form_for @item do |f|%> <%= f.file_field :photo, accept: 'image/png,image/jpeg'%> <% end %> 将仅依赖于接口,该接口的耦合程度低于依赖于类的接口。

旁注: [jsfiddle.net/c2dcu045/1/][1] 是一个令人困惑的变量名,因为它看起来像一个常量或类名。使用function series_types() { ?> <div class="form-field term-description-wrap"> <label for="tag-type">Type</label> <input type='text' name='tag-type'></input> </div> <?php } endif; add_action('series_add_form_fields', 'series_types'); 会更常规。

答案 1 :(得分:0)

如果Product是抽象的,那么您的代码只会隐藏依赖关系,并且&#34;产品B&#34;实际上是该类的一些衍生物的实例,例如&#34; MobileProduct&#34;, 如果产品不是抽象的,你只能隐藏&#34;产品&#34;而不是它的存在。

或者如果工厂是抽象的,那么你实际上隐藏了生产产品的许多方法。例如,如果您有一个&#34; SqlProductFactory&#34;或&#34; InMemoryProductFactory&#34;。然后,您隐藏了对产品的存储,创建或来源的依赖性。

天气与否工厂是否有利于设计,高度取决于您的问题,以及如何解决。例如,如果您正在构建一个大型API或库,那么隐藏一些消费者不需要了解的依赖关系可能是有意义的。但如果你只需要解决&#34; Hello World&#34;或者&#34; FizzBu​​zz&#34;一个班级真的不需要 - 更不用说工厂了。

为了回答您的问题,您的代码是否隐藏了依赖关系?这是好的设计吗?那么在这两种情况下都取决于手头的问题。

EnemyBase {
 int Hitpoints;
 int Damage;
 void Speak();
}

EasyEnemy : EnemyBase {
   public int Hitpoints = 100;
   public int Damage = 20;
   private string Name = "EZGuy";
   public void Speak(){
      print this.Name + ": I shall destroy you!";
   }
}

HardEnemy : EnemyBase {
   public int Hitpoints = 200;
   public int Damage = 40;
   private string Name = "Da hard1";
   public void Speak(){
      print this.Name + ": Your days are numbered!";
   }{
}

EnemyFactory {
  private int EnemiesProduced = 0;
  public EnemyBase getEnemy(){
     if(IsOdd(++this.EnemiesProduced)){
        return new EasyEnemy();
     } else {
        return new HardEnemy();
     }
  }
}

Game {
  EnemyFactory enemies;
  public Game(EnemyFactory factory){
     enemies = factory;
  }
  public void Start(){
     EnemyBase e = factory.getEnemy();
  }
}

这里游戏对HardEnemy或EasyEnemy一无所知,只关心获得EnemyBase。它也只知道两个公共字段,以及EnemyBase类提供的speak方法。这可能是也可能不是好事。例如,它使我们能够改变敌人的实施,而不必改变游戏,这让我们专注于发展敌人并测试它们如何影响游戏 - 而不必对游戏给予任何关注。因此,这可能是一件非常好的事情,让您可以更快地开发,也可以在团队之间开发,或者为您的解决方案提供未来证明。但它也可能是一个完全不必要的复杂层 -

所以总结:)这真的取决于:)(Pun可能会或可能不会打算)