抽象工厂是否引入了紧耦合

时间:2016-04-07 19:16:45

标签: oop design-patterns factory factory-pattern abstract-factory

我有一个场景,我认为我不是严格编码到接口。 让我们说我有一个界面(在某些程序集中)

public interface IFoo
{
    void GetSomething();
    void SaveSomething();
}

现在,我有一个实现(在其他一些程序集中)

public class FoodB : IFoo
{
   public FoodB(Guid guid, IFoodBConfig config)  //IFoodBConfig is defined in same library where FoodB exists
   {
      ...
   }
}

因此,基本上实现需要guid和config

现在,我有一个客户端(在其他一些程序集中)希望使用IFoo,例如

public class Client
{
    public Client(IFoo foo)
    {
       ...
    }
}

DIP说必须在组合根处提供实现,并且客户端不能实例化对象本身。好的很棒。

现在,组合根或IoC容器决定将FoodB作为具体实例注入,但它没有#guid'的值。因为它仅在运行时期间可用。

所以,我们决定抽象工厂。

public abstract FooFactory
{
    public abstract IFoo GetFoo(Guid guid, IFoodBConfig config);
}

现在,提出了几个问题

a)必须修改客户端构造函数以接受FooFactory而不是IFoo,这意味着客户端已经决定使用哪种实现。在我看来,这使软件紧密耦合

b)即使客户端构造函数被修改为接受FooFactory,也必须将IFoodBConfig具体提供给构造函数,现在这将使客户端引用存在FoodB的库。

c)工厂申报和实施将在何处进行?将FooFactory放在声明IFoo的库中是不正确的,因为工厂与IFoo无关。由于相同的原因,将FooFactory放入FoodB库也不正确

d)简单地使用抽象工厂意味着交换实现的灵活性已经消失,因为客户端的目录与FoodBFactory绑定。

这种做法是不正确的还是我们必须忍受的一些限制?

1 个答案:

答案 0 :(得分:3)

在这个问题中要解决几点。

  1. FooFactory不是Abstract Factory的示例,至少是GoF术语。
    Abstract Factory!=名为Factory的抽象类。
  2. 组合根不需要在编译时具有所有参数。现代IoC容器应该都支持运行时参数。
  3. a)正如@dbugger评论的那样,将客户端耦合到抽象类与耦合到接口没有区别。

    b)可以使用FooBFactory预先配置FooBConfig实施或IoC容器。然后客户端只传递其运行时guid。

    c)FooFactoryIFoo直接相关,因为其目的是返回IFoo的实例。实际上,它的方法的返回类型是IFoo

    d)灵活性的存在是因为IoC容器可以将Factory Method的不同实现注入客户端,允许客户端获取不同的产品,而无需了解产品实现或用于实例化它的工厂实现。

    如果您愿意将客户端连接到IoC容器,客户端可以直接将容器用作工厂,从而消除了额外的工厂接口。