【问题标题】:Does injecting a factory hide a dependency?注入工厂会隐藏依赖项吗?
【发布时间】:2017-02-16 12:49:50
【问题描述】:

A 有一个字段factory,它产生一个产品Bfactory 是使用依赖注入注入的。注入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
    }

}

【问题讨论】:

  • 工厂是一个额外的间接层,它是often unneeded
  • 请详细说明您提出问题的目的。我可以回答“是的,它确实隐藏了这种依赖关系”,但我不确定这是否对你有帮助。

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


【解决方案1】:

不,从 Factory 获取 Product 不会隐藏依赖关系。 A 定义了getProduct,它返回Product,所以A 依赖于Product

即使你内联了getProductA 也会依赖于Factory,而Factory 又依赖于Product,这也是耦合的。

AProduct 解耦的常规方法是将Product 类分离为接口ProductProductImpl 类(或其他),并使用依赖注入或工厂(一次通常都过大了)在不知道实现类的情况下获取Product 的实例。那么A 将只依赖于一个接口,它的耦合度低于依赖于一个类。

旁注:B 是一个容易混淆的变量名,因为它看起来像一个常量或类名。使用b 会更传统。

【讨论】:

    【解决方案2】:

    如果 Product 是抽象的,您的代码只会隐藏依赖项,并且“Product B”实际上是该类的某些派生类的实例,例如“MobileProduct”, 如果 Product 不是抽象的,你只会隐藏“Product”的实现而不是它的存在。

    或者,如果工厂是抽象的东西,那么您实际上隐藏了生产产品的多种方式。例如,如果您有“SqlProductFactory”或“InMemoryProductFactory”。然后隐藏对产品如何存储、创建或来源的依赖关系。

    工厂是否适合设计,很大程度上取决于您的问题以及如何解决。例如,如果您正在构建一个大型 API 或库,那么隐藏一些消费者不需要知道的依赖项可能是有意义的。但是,如果您只需要解决“Hello World”或“FizzBu​​zz”,那么就不需要一个类——更不用说一个工厂了。

    所以为了回答你的问题,你的代码是否隐藏了依赖关系?是好的设计吗?好吧,这两种情况都取决于手头的问题。

    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();
      }
    }
    

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

    因此得出结论 :) 这真的取决于 :) (双关语可能是有意的,也可能不是有意的)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-09
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      相关资源
      最近更新 更多