【发布时间】:2016-04-07 19:16:44
【问题描述】:
我有一个场景,我认为我没有严格地对接口进行编码。 假设我有一个接口(在某些程序集中)
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 的目录。
这种方法是否不正确,或者这是我们必须忍受的一些限制?
【问题讨论】:
-
a) 抽象类不能被实例化,它不是一个实现。你只耦合到抽象类的接口。 b) 如果你想使用某些东西,你必须引用它的库 c) 工厂创建 IFoo,但与 IFoo 无关? d) 不,它与抽象的 FooFactory 相关联
-
这是否意味着
FooFactory本质上应该重命名为公共接口FoodBFactory以明确声明它只创建FoodB类型?
标签: oop design-patterns factory factory-pattern abstract-factory