天天看點

設計模式之工廠模式—— .NET Core 源碼中的使用

工廠模式實作三種方式

實作工廠模式的方式有以下三種:

1. 簡單工廠模式:通過一個工廠類來建立對象執行個體,用戶端隻需提供所需産品的類型即可。實作方式比較簡單,但是不夠靈活,新增産品時需要修改工廠類。

2. 工廠方法模式:将工廠類抽象成一個接口,讓子類來決定具體建立哪個産品。用戶端隻需知道工廠接口和相應産品接口即可。更加靈活,但是需要定義大量的接口和類。

3. 抽象工廠模式:用于建立一系列相關的産品對象,為這些産品提供一個共同的接口。用戶端隻需要知道抽象工廠接口和相應産品接口即可。适用于産品族的建立。

一、簡單工廠模式

簡單工廠模式是建立型設計模式之一,它通過一個工廠類來建立對象執行個體,而不是直接使用 new 關鍵字來執行個體化對象。在該模式中,用戶端隻需知道所需産品的類型即可,而無需關心實際的實作細節。

簡單工廠模式适用于以下場景:

1. 需要建立的對象較少,不會經常增加新的産品。

2. 用戶端隻需要知道所需産品的類型,而無需關心實作細節。

3. 類的建立過程比較簡單,且用戶端無需知道類的建立細節。

在 .NET Core 源碼中,簡單工廠模式的應用非常廣泛,例如:

1. System.Configuration.ConfigurationManager 類中的 GetSection() 方法,用于擷取指定配置節的資訊。

2. System.IO.File 類中的 Create() 方法,用于建立指定檔案的 FileStream 對象。

3. System.Net.WebRequest 類中的 Create() 方法,用于建立 WebRequest 對象。

以上這些方法都是使用簡單工廠模式實作的,它們根據參數類型的不同來建立不同的對象執行個體。

簡單工廠模式在 .NET Core 源碼中的實作事例

public interface ILogger
{
    void Log(string message);
}

public class FileLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(#34;Logging to file: {message}");
    }
}

public class DatabaseLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(#34;Logging to database: {message}");
    }
}

public static class LoggerFactory
{
    public static ILogger GetLogger(string loggerType)
    {
        switch (loggerType.ToLower())
        {
            case "file":
                return new FileLogger();
            case "database":
                return new DatabaseLogger();
            default:
                throw new ArgumentException(#34;Invalid logger type: {loggerType}");
        }
    }
}

// 使用示例
ILogger logger = LoggerFactory.GetLogger("file");
logger.Log("Hello, world!");           

在上面的例子中,我們定義了一個 `ILogger` 接口和兩個實作類 `FileLogger` 和 `DatabaseLogger`。然後通過 `LoggerFactory` 工廠類來建立具體的 `ILogger` 執行個體,用戶端隻需要提供所需的 `loggerType` 參數即可。在使用時,先通過工廠類擷取對應的執行個體,然後調用其 `Log()` 方法輸出日志。

工廠方法模式在 .NET Core 源碼中使用

一個典型的例子就是 EF Core 中的 `DbContext` 類。`DbContext` 用于與資料庫互動,而不同的資料庫需要使用不同的資料庫提供程式(或稱為“資料驅動程式”)。EF Core 的工廠方法模式實作了讓使用者自行選擇所需資料庫提供程式的功能。

下面以 SQLite 資料庫提供程式為例,示範 EF Core 中工廠方法模式的實作:

首先,定義一個抽象的 `DbContext` 工廠類:

public abstract class DbContextFactory
{
    protected abstract DbContext CreateNewInstance(string connectionString);

    public DbContext Create(string connectionString)
    {
        return CreateNewInstance(connectionString);
    }
}           

然後,定義一個具體的 `SQLiteDbContextFactory` 工廠類,繼承自抽象工廠類,并實作具體的 `CreateNewInstance()` 方法,用于建立 SQLite 資料庫的 `DbContext` 執行個體:

public class SQLiteDbContextFactory : DbContextFactory
{
    protected override DbContext CreateNewInstance(string connectionString)
    {
        var optionsBuilder = new DbContextOptionsBuilder<SQLiteDbContext>();
        optionsBuilder.UseSqlite(connectionString);

        return new SQLiteDbContext(optionsBuilder.Options);
    }
}           

注意到上述代碼中,我們通過 `DbContextOptionsBuilder` 類建立了 `DbContext` 的選項,并将其傳遞給實際建立執行個體的構造函數。

最後,使用時,隻需要先建立一個具體的 `DbContextFactory` 執行個體,然後調用其 `Create()` 方法建立所需的 `DbContext` 執行個體即可:

var factory = new SQLiteDbContextFactory();
var context = factory.Create("Data Source=example.db");           

在上述代碼中,我們建立了一個 `SQLiteDbContextFactory` 執行個體,并使用其 `Create()` 方法建立了一個 SQLite 資料庫連接配接的 `DbContext` 執行個體。

總之,工廠方法模式是一種很常見的設計模式,在 .NET Core 中得到了廣泛應用。`DbContext` 工廠也是其中的一個經典例子。

抽象工廠模式在 .NET Core 中也有應用

最常見的就是 ADO.NET 中的資料提供程式(Data Provider)。

首先,定義一個抽象的 `DbProviderFactory` 類,表示一個通用的資料庫提供程式工廠:

public abstract class DbProviderFactory
{
    public abstract DbCommand CreateCommand();
    public abstract DbConnection CreateConnection();
    public abstract DbParameter CreateParameter();
}           

注意到上面的 `DbProviderFactory` 類中定義了三個抽象方法,分别用于建立 `DbCommand`、`DbConnection` 和 `DbParameter` 對象。這些對象都是和資料庫相關的核心對象。

接着,定義一個具體的 `SqlClientFactory` 類,繼承自抽象工廠類,并實作具體的 `Create*()` 方法,用于建立 Microsoft SQL Server 資料庫提供程式的對象:

public class SqlClientFactory : DbProviderFactory
{
    public override DbCommand CreateCommand()
    {
        return new SqlCommand();
    }

    public override DbConnection CreateConnection()
    {
        return new SqlConnection();
    }

    public override DbParameter CreateParameter()
    {
        return new SqlParameter();
    }
}           

類似的,還可以定義其他的具體工廠類,用于建立不同的資料庫提供程式對象。

最後,在使用時,隻需要先建立一個具體的 `DbProviderFactory` 執行個體,然後調用其 `Create*()` 方法即可建立所需的對象(如 `DbCommand`、`DbConnection` 等):

// 建立一個 SQL Server 資料庫提供程式工廠執行個體
var factory = SqlClientFactory.Instance;

// 使用該工廠建立對象
using (var connection = factory.CreateConnection())
{
    connection.ConnectionString = connectionString;
    connection.Open();

    using (var command = factory.CreateCommand())
    {
        command.CommandText = "SELECT * FROM Customers";
        command.Connection = connection;

        using (var reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                // 讀取資料
            }
        }
    }
}           

上述代碼中,我們首先建立了一個 `SqlClientFactory` 執行個體,然後使用該執行個體建立了 `SqlConnection` 和 `SqlCommand` 對象。注意到,在使用 `DbCommand` 和 `DbConnection` 等對象時,并沒有直接寫明其具體的類型,而是通過 `DbProviderFactory` 提供的抽象方法進行了建立,這正是抽象工廠模式的精髓所在。

綜上,抽象工廠模式在 .NET Core 中得到廣泛應用,尤其是在 ADO.NET 資料提供程式中。通過使用抽象工廠模式,我們可以輕松地切換不同的資料庫提供程式,加強了系統的靈活性和可擴充性。

繼續閱讀