Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这是一个很好的工厂方法实现吗?_C#_Factory Method - Fatal编程技术网

C# 这是一个很好的工厂方法实现吗?

C# 这是一个很好的工厂方法实现吗?,c#,factory-method,C#,Factory Method,我正在开发一个需要严格解耦接口的模块。具体地说,在实例化根对象(数据源)之后,用户只需要通过接口与对象模型交互。我有实际的工厂对象(我称之为提供者)来提供实现这些接口的实例,但这留下了获取提供者的笨拙。为此,我在数据源上提供了两种方法: public class MyDataSource { private Dictionary<Type, Type> providerInterfaceMapping = new Dictionary<Type, Type>()

我正在开发一个需要严格解耦接口的模块。具体地说,在实例化根对象(数据源)之后,用户只需要通过接口与对象模型交互。我有实际的工厂对象(我称之为提供者)来提供实现这些接口的实例,但这留下了获取提供者的笨拙。为此,我在数据源上提供了两种方法:

public class MyDataSource
{
    private Dictionary<Type, Type> providerInterfaceMapping = new Dictionary<Type, Type>()
    {
        { typeof(IFooProvider), typeof(FooProvider) },
        { typeof(IBarProvider), typeof(BarProvider) },
        // And so forth
    };

    public TProviderInterface GetProvider<TProviderInterface>()
    {
        try
        {
            Type impl = providerInterfaceMapping[typeof(TProviderInterface)];
            var inst = Activator.CreateInstance(impl);

            return (TProviderInterface)inst;
        }
        catch(KeyNotFoundException ex)
        {
            throw new NotSupportedException("The requested interface could not be provided.", ex);
        }
    }
}
公共类MyDataSource
{
private Dictionary providerInterfaceMapping=新字典()
{
{typeof(IFooProvider),typeof(foopprovider)},
{typeof(IBarProvider),typeof(BarProvider)},
//诸如此类
};
公共TProviderInterface GetProvider()
{
尝试
{
Type impl=providerInterfaceMapping[typeof(TProviderInterface)];
var inst=Activator.CreateInstance(impl);
返回(TProviderInterface)指令;
}
捕获(KeyNotFoundException ex)
{
抛出新的NotSupportedException(“无法提供请求的接口。”,ex);
}
}
}

我动态地修改了一些细节以简化(例如,此代码段不包括传递给已创建的实现实例的参数)。这是在C#中实现工厂方法的一种很好的通用方法吗?

您应该后退一步,问问使用工厂方法是否是一个好主意?在我看来,不是这样

factory方法存在不止一个问题,您的示例说明了几个问题:

  • 您需要对实现进行硬引用(除了IFooProvider之外还有foopprovider),这正是您首先要避免的情况。即使您的其余代码只使用IFooProvider,您的库仍然与FooProvider紧密耦合。如果其他开发人员不知道您的工厂方法,他/她可能会来直接使用FooProvider
  • 您只支持具有默认构造函数的实现,因为您使用的是Activator.CreateInstance。这会阻止您使用嵌套依赖项

与其尝试手动控制依赖项,我建议您看看依赖项注入(DI)。每当你的代码需要一个iFoopProvider时,就为它提供构造函数注入。

从技术上讲这很好,但是大多数时候当我看到工厂时,它通常返回相同类型的接口,例如类似于
IProvider
的接口,而不是
iFoopProvider
IBarProvider
,这对我来说没有意义。如果您要使用FooProvider和BarProvider,那么为什么要为它们使用不同的接口呢。我将使用一个接口
IProvider
,并让
FooProvider
BarProvider
实现它。

无论使用工厂方法的正确性或错误性如何(因为这不是您所要求的!),您的实现在我看来都很好


比硬编码类型映射更好的方法是将信息放入配置文件并加载到应用程序中。

不要重新设计自己的实现,使用现有库或应用程序块


注入依赖项是一个常见的编程问题,您不必自己解决。有一些很好的轻量级库(我在上面提到了几个)可以很好地完成这项工作。它们支持定义依赖项的声明式模型和命令式模型,并且非常擅长于它们的工作。

我一直在使用这种模式,并将这种逻辑抽象为可重用的程序集。它使用反射、泛型和属性在运行时定位和绑定具体类型


这有助于解决Mark的问题,因为实现类型不是硬编码的,而且实现类型是由安装而不是在项目程序集引用中确定的。

您说得很对,事实上,
IFooProvider
IBarProvider
都从公共位的
IProvider
继承<代码>Foos、
baz
在构造上都采用不同的参数,因此它们的创建方法签名是不同的。我不想这样做,但出于(愚蠢的)政治原因,在我的公司环境中,任何一种感知到的外部依赖都是自动的、即时的损失。对于ORM也是如此(这正是我真正想要使用的)。我们甚至不能使用Boost。是的,这是一个非常严重的自我毁灭性NIH病例。是的,它会自我毁灭,甚至会杀死组织。这是我下岗前的最后一项任务。在过去的五年里,我一直在努力打好这场仗,但我不擅长销售或政治,当我发现我和60-70%的同事被解雇,所有的开发工作都被运往海外时,是时候停止向风车倾斜了。是的,这是一个不幸的情况。我希望你能在下一个职位上成为一个更开明的组织的一员,祝你好运。我同意。:)我正在争取。我已经拒绝了一个提议,因为它看起来像是一个类似的情况,我已经受够了那些废话。我不明白为什么一家公司会拒绝接受行业知识而不是接受它我不确定我是否理解你的第一点。客户端无法访问FoopProvider,只能访问IfoopProvider。FooProvider是程序集的内部。或者我没有领会你的意思?Re:第二点,我确实支持使用参数的实现。正如我在问题中提到的,我从我包含的示例中省略了这一点,只是为了让它更简单。不过,这有点笨拙——提供者都希望将一个数据源作为他们唯一的parm,并获得