65.9K
CodeProject 正在变化。 阅读更多。
Home

学习 C# 中的工厂模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (28投票s)

2016年1月31日

CPOL

3分钟阅读

viewsIcon

39315

downloadIcon

345

使用简单的工厂工厂在 C# 中解释工厂模式

引言

工厂模式在编程中非常常见。 如果您检查 .NET Framework 或任何其他框架,您会发现工厂模式被广泛使用,这表明了它的受欢迎程度。 工厂模式属于创建型模式,它处理对象创建。 在本文中,我们将尝试使用简单的 C# 控制台应用程序来学习工厂模式。

背景

当我们编写代码时,我们会遇到根据某些 if 条件或 switch 语句创建对象的情况。 如果这种对象创建不是基于经过验证的设计模式,那么我们实际上是在使对象创建变得复杂,并且未来的增强非常困难。 此时,我们应该考虑使用工厂模式来抽象对象创建逻辑的复杂性,并使未来的添加变得无忧。

让我们以一个项目中记录功能的非常简单的例子为例。 如果我们的实现如下所示,那么添加一个新的日志记录选项需要在客户端代码库中进行大量的代码更改,这不是一个好的做法。

public void Log(string message, string type)
{
    switch (type)
    {
        case "Database":
            DatabaseLogger databaseLogger =  new DatabaseLogger();
            databaseLogger.Log(message);
            break;
        case "EventViewer":
        default:
            EventViewerLogger eventviewerLogger =  new EventViewerLogger();
            eventviewerLogger.Log(message);
            break;
    }
}

工厂模式无非是从客户端隐藏对象创建逻辑,这样最终客户端就不必担心对象创建逻辑,而是客户端可以使用公共接口来引用工厂模式创建的对象。

Using the Code

为了更好地理解,我们可以创建一个简单的 Logger Factory,它将帮助客户端根据他们的选择将消息记录到不同的选项中。

Factory  Pattern Example in C#

首先,我们需要创建一个接口或 abstract 类作为所有类的基类,这些类我们将在工厂中创建实例。 在这里,我使用了一个带有方法 Log 消息的接口 ILogger

 interface ILogger
{
    void Log(string Message);
}

现在,我们将在所有要从 Logger Factory 返回的类中实现此 ILogger。 在这里,理想情况下,Log 方法应该有将消息记录到文件的实际方法,但为了演示目的,我只是添加了一条控制台消息。

class FileLogger : ILogger
{
    public void Log(string Message)
    {
        Console.WriteLine("{0} - Logged in File.", Message);
    }
}

以同样的方式将 ILogger 实现到 DatabaseLogger,也添加了 Log 方法定义。

class DatabaseLogger : ILogger
{
    public void Log(string Message)
    {
        Console.WriteLine("{0} - Logged in Database.", Message);
    }
}

EventViewerLogger 也从 ILogger 实现,并根据类型添加了 Log 方法定义。 我们可以添加新的 logger 类,这些类与这些 logger 类相同。

class EventViewerLogger : ILogger
{
    public void Log(string Message)
    {
        Console.WriteLine("{0} - Logged in EventViewer.", Message);
    }
}

创建一个 enum 以轻松识别 LoggerType,以防我们有一个新的 LoggerType,那么我们可以在这里添加它。

enum LoggerType
{
    File,
    Database,
    EventViewer
}

最后,我们到达了 LoggerFactory。 现在,这个工厂将根据 enum 值负责对象创建,并将创建的实例返回给客户端代码,该代码将是 ILogger 类型。

class LoggerFactory
{
    public static ILogger Get(LoggerType type)
    {
        switch (type)
        {
            case LoggerType.Database:
                return new DatabaseLogger();
            case LoggerType.EventViewer:
                return new EventViewerLogger();
            case LoggerType.File:
            default:
                return new FileLogger();
        }
    }
}

如果您查看上面的代码,您可以看到对象创建逻辑在工厂中被抽象出来,并且对象是根据所请求的对象类型创建的,因为返回类型是接口 ILogger,客户端代码不需要担心向工厂添加新内容。

我编写了一个客户端代码来使用此工厂,如下所示

static void Main(string[] args)
{
    ILogger logger1 = LoggerFactory.Get(LoggerType.Database);
    logger1.Log("Message from Main");

    ILogger logger2 = LoggerFactory.Get(LoggerType.File);
    logger2.Log("Message from Main");

    ILogger logger3 = LoggerFactory.Get(LoggerType.EventViewer);
    logger3.Log("Message from Main");

    Console.ReadKey();

    /*Output
    Message from Main - Logged in Database.
    Message from Main - Logged in File.
    Message from Main - Logged in EventViewer.
    */
}

在上面的代码中,客户端代码使用 enum 请求一个特定的对象,并使用该对象调用 log 方法。 对象是使用 ILogger 创建的,并使用工厂实例化。 我在下面给出了输出

要自己探索此示例,您可以下载附加的代码,或者创建一个名为“FactoryPatternSample”的控制台项目,并将 Program.cs 的内容替换为以下代码块。

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FactoryPatternSample
{
    class Program
    {
        interface ILogger
        {
            void Log(string Message);
        }

        enum LoggerType
        {
            File,
            Database,
            EventViewer
        }

        class FileLogger : ILogger
        {
            public void Log(string Message)
            {
                Console.WriteLine("{0} - Logged in File.", Message);
            }
        }

        class DatabaseLogger : ILogger
        {
            public void Log(string Message)
            {
                Console.WriteLine("{0} - Logged in Database.", Message);
            }
        }

        class EventViewerLogger : ILogger
        {
            public void Log(string Message)
            {
                Console.WriteLine("{0} - Logged in EventViewer.", Message);
            }
        }

        class LoggerFactory
        {
            public static ILogger Get(LoggerType type)
            {
                switch (type)
                {
                    case LoggerType.Database:
                        return new DatabaseLogger();
                    case LoggerType.EventViewer:
                        return new EventViewerLogger();
                    case LoggerType.File:
                    default:
                        return new FileLogger();
                }
            }
        }

        static void Main(string[] args)
        {
            ILogger logger1 = LoggerFactory.Get(LoggerType.Database);
            logger1.Log("Message from Main");

            ILogger logger2 = LoggerFactory.Get(LoggerType.File);
            logger2.Log("Message from Main");

            ILogger logger3 = LoggerFactory.Get(LoggerType.EventViewer);
            logger3.Log("Message from Main");

            Console.ReadKey();

            /*Output
            Message from Main - Logged in Database.
            Message from Main - Logged in File.
            Message from Main - Logged in EventViewer.
            */
        }
    }
}

摘要

在本文中,我使用一个简单的 C# 应用程序解释了工厂模式。 我希望您喜欢这篇文章,并且对您的知识有所补充。 请不要忘记标记您的投票、建议和反馈,以提高本文和即将发布的文章的质量。

历史

  • 2016 年 1 月 31 日:初始版本
© . All rights reserved.