Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.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#_Design Patterns_Factory - Fatal编程技术网

C#:提供程序与工厂类示例

C#:提供程序与工厂类示例,c#,design-patterns,factory,C#,Design Patterns,Factory,我使用类LoggerProvider来提供ILogger。对于ILogger的每个具体实现,我都使用特定的命名方法。我在考虑结构,我能说这个提供者类是工厂类吗 public class LoggerProvider { public static ILogger GetDbLogger() { return new DBLogger(); } public static ILogger GetEmailLogger(string email)

我使用类LoggerProvider来提供ILogger。对于ILogger的每个具体实现,我都使用特定的命名方法。我在考虑结构,我能说这个提供者类是工厂类吗

public class LoggerProvider
{
    public static ILogger GetDbLogger()
    {
        return new DBLogger();
    }

    public static ILogger GetEmailLogger(string email)
    {
        return new EmailLogger(email);
    }

    public static ILogger GetTxtLogger()
    {
        return new TxtLogger(new BaseTxtLoggerConfiguration(), ProjectManager.GetInstance().GetCurrentProjectSettings());
    }
}

public class CustomerOneService
{
    private readonly ILogger _logger;

    public CustomerOneService()
        : this(LoggerProvider.GetDbLogger())
    { }

    public CustomerOneService(ILogger logger)
    {
        _logger = logger;
    }

    public void Import()
    {
        // some operation with _logger
    }
}
public class CustomerTwoService
{
    private readonly ILogger _logger;

    public CustomerTwoService()
        : this(LoggerProvider.GetTxtLogger())
    { }

    public CustomerTwoService(ILogger logger)
    {
        _logger = logger;
    }

    public void CopyData()
    {
        // some operation with _logger
    }
}
因为若我正确理解了工厂的用途,它用于提供特定接口的实例,但在运行时由工厂返回哪个具体实现来决定,例如,从用户界面返回的一些输入作为参数传递给工厂。但另一方面,另一个目的是提供实例并处理创建对象的问题——当客户机不关心实例是如何创建的时候。我的提供者应用第二个原则,但不是第一个原则


我检查了这篇文章,但根据工厂和供应商的定义,我仍然不确定哪篇文章适合我的情况。

简而言之,这取决于使用情况。如果CustomerService和CustomerTwoService的多个实例可能共享相同的记录器实例,则提供程序。“提供者”意味着您不在乎是否获得了一个新的共享实例,只要您得到了可以使用的东西

如果一个/两个服务要求每个实例都获得一个记录器的新实例,则需要一个工厂。“工厂”意味着每次调用它的“CreateXYZ”方法时,都会得到一个新实例

如果One/TwoService要求每个实例都获得记录器的独占实例,则需要一个池。“Pool”意味着每次调用它的一个“GetXYZ”方法时,都会得到一个只供您使用的实例。然后,在完成该实例后,最好“释放”该实例。“Pool”并不意味着每次都是一个新实例。它可以重复使用。但在你发布之前,你会得到它的独家使用权

苏。。你可以说工厂是一种提供者,而池是一种提供者。但当然,游泳池不是工厂

Soo#2,您的
日志提供者
当然是一个提供者,但从其实现来看,它也是一个工厂。无论你称它为一个还是另一个,取决于你想让它的用户知道它是一个保证总是得到一个新对象的工厂

可能还有其他模式。。但也许你明白了。它在使用上没有太大的不同(嘿,你有一个X,它给你y)。这一切都取决于您管理/分发的资源,而命名主要是为了提示您可以从对象源中期望什么行为

我不知道哪一个最适合你的情况。这取决于如何使用日志记录器,它们有哪些限制,以及您希望花费多少时间来实现和管理一个池。工厂/提供者通常比池简单得多

此外,由于一个/两个服务似乎在构造函数中得到它们的依赖关系,所以考虑使用DI/IOCC。而不是通过硬编码工厂/供应商等进行静态查找

public CustomerTwoService()
    : this(LoggerProvider.GetTxtLogger())
考虑

public CustomerTwoService(ILogger logger)
    : this(logger)
然后配置IoC容器,以便CustomerTwoService获得TxtLogger


如果没有一个工作的IoC容器,这是不可能的,第一次将它引入到您的项目中是另一个单独的主题(但在概念上与您现在正在分析的内容类似,所以它在某种程度上是在这个问题的上下文中),但值得一看,尤其是当您需要许多组件和/或许多依赖项时。

您的
LoggerProvider
几乎与此完全相同:

公共枚举场景
{
IWantADbLogger,
伊万塔内米洛格,
IWantATxtLogger
}
公共类日志提供程序
{
公共静态ILogger GetLogger(场景)
{
切换(场景)
{
case Scenario.IWantADbLogger:返回新的DbLogger();
//等等等等等等
}
}
}
它看起来更像一个工厂,因为它表明它为您决定返回的内容(即使在本例中它不使用它,并且实际上与原始代码相同)

即使是一个运行时回旋余地很小的糟糕工厂,如果它为您生成了一些东西,而您没有确定这些东西到底是什么,那么它仍然是一个工厂,我认为您的代码就是这样做的。如果您的
LoggerProvider
愿意,它可以连接并返回一个构造稍有不同的TxtLogger,而调用者不会知道这一点。只要它在为打电话的人做决定,它就是一个工厂

当然,供应商也这样做!服务也是如此,基本上存在的所有其他封装类都是这样做的。那么有什么区别呢

工厂取代了建筑工人。它们创建的是对象,而不是数据,这些对象属于您,就像使用构造函数一样。你必须自己储存这个东西如果你想把它放在周围,你必须妥善处理它,诸如此类的事情。除非你把它送到别的地方,否则它不会住在别的地方


然后,通过在运行时在构造函数中保留一些可供选择的元素,它们(稍微)将自己与构造函数区分开来。选择越多越好。

试着为
Import
CopyData
方法编写一个单元测试。@AlexanderPetrov我认为这现在是个问题,但我认为对于这个例子来说,这并不重要,不是吗?我将在服务中更新代码以使其可测试。您是否在.NET Framework中?还是核心?@caseycrokston.NET Framework