c# 设计模式--抽象工厂模式 (Abstract Factory)

定义

抽象工厂模式是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式强调的是对象族的创建,而不是单一对象的创建。

用例写法

假设我们有一个场景,需要根据不同的平台(如 Windows 和 MacOS)创建不同的用户界面组件(如按钮和文本框)。

csharp 复制代码
// 用户界面组件接口
public interface IButton
{
    void Render();
}

public interface ITextBox
{
    void Render();
}

// Windows用户界面组件
public class WindowsButton : IButton
{
    public void Render() => Console.WriteLine("Rendering Windows Button...");
}

public class WindowsTextBox : ITextBox
{
    public void Render() => Console.WriteLine("Rendering Windows TextBox...");
}

// MacOS用户界面组件
public class MacOSButton : IButton
{
    public void Render() => Console.WriteLine("Rendering MacOS Button...");
}

public class MacOSTextBox : ITextBox
{
    public void Render() => Console.WriteLine("Rendering MacOS TextBox...");
}

// 抽象工厂接口
public interface IUIComponentFactory
{
    IButton CreateButton();
    ITextBox CreateTextBox();
}

// Windows用户界面组件工厂
public class WindowsUIComponentFactory : IUIComponentFactory
{
    public IButton CreateButton() => new WindowsButton();
    public ITextBox CreateTextBox() => new WindowsTextBox();
}

// MacOS用户界面组件工厂
public class MacOSUIComponentFactory : IUIComponentFactory
{
    public IButton CreateButton() => new MacOSButton();
    public ITextBox CreateTextBox() => new MacOSTextBox();
}

// 配置类
public class Configuration
{
    public string OS { get; set; }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        Configuration config = new Configuration { OS = "Windows" };

        IUIComponentFactory factory;
        if (config.OS == "Windows")
        {
            factory = new WindowsUIComponentFactory();
        }
        else if (config.OS == "MacOS")
        {
            factory = new MacOSUIComponentFactory();
        }
        else
        {
            throw new ArgumentException("Unsupported operating system");
        }

        IButton button = factory.CreateButton();
        ITextBox textBox = factory.CreateTextBox();

        button.Render();
        textBox.Render();
    }
}

类图:

IButton +void Render() ITextBox +void Render() WindowsButton +void Render() WindowsTextBox +void Render() MacOSButton +void Render() MacOSTextBox +void Render() IUIComponentFactory +IButton CreateButton() +ITextBox CreateTextBox() WindowsUIComponentFactory +IButton CreateButton() +ITextBox CreateTextBox() MacOSUIComponentFactory +IButton CreateButton() +ITextBox CreateTextBox() Configuration -string OS +Configuration() Program +static void Main(string[] args)

解释

  1. 用户界面组件接口 (IButtonITextBox):定义了渲染按钮和文本框的方法。
  2. 具体用户界面组件 (WindowsButtonWindowsTextBoxMacOSButtonMacOSTextBox):实现了具体的按钮和文本框渲染逻辑。
  3. 抽象工厂接口 (IUIComponentFactory):定义了创建按钮和文本框的方法。
  4. 具体工厂类 (WindowsUIComponentFactoryMacOSUIComponentFactory):实现了具体的按钮和文本框创建逻辑。
  5. 配置类 (Configuration):用于存储操作系统的配置信息。
  6. 客户端代码 (Program):根据配置信息选择合适的工厂类,并使用工厂类创建具体的用户界面组件,然后调用其渲染方法。

用途

  1. 创建一系列相关对象:当需要创建一系列相关或相互依赖的对象时,使用抽象工厂模式可以确保这些对象的一致性。
  2. 解耦对象的创建和使用:客户端代码只需要依赖抽象工厂接口,不需要知道具体的产品类,从而降低了耦合度。
  3. 支持多平台:适用于需要在不同平台上创建不同版本的对象的场景。

优点

  1. 易于交换产品族:可以在运行时动态地切换不同的产品族,只需更换工厂对象即可。
  2. 支持开闭原则:增加新的产品族时,只需要添加新的具体工厂类,不需要修改现有的代码,符合开闭原则。
  3. 高度模块化:每个产品族的创建逻辑都封装在对应的工厂类中,模块化程度高。

缺点

  1. 系统复杂度增加:引入了更多的接口和类,系统结构变得更复杂。
  2. 增加代码量:每增加一个新的产品族,都需要增加相应的工厂类和产品类。
  3. 产品族扩展困难:如果需要增加新的产品类型,必须修改所有的工厂类,这违反了开闭原则。

适用场景

  1. 产品族多:当系统中有多个产品族,且每个产品族中的产品需要一起使用时。
  2. 多平台支持:需要在不同平台上创建不同版本的对象时。
  3. 对象创建逻辑复杂:对象的创建逻辑较为复杂,需要集中管理和控制时。

实际开发中的应用

1. 多平台用户界面框架

假设我们正在开发一个多平台用户界面框架,需要根据不同的操作系统创建不同的用户界面组件。

csharp 复制代码
// 用户界面组件接口
public interface IButton
{
    void Render();
}

public interface ITextBox
{
    void Render();
}

// Windows用户界面组件
public class WindowsButton : IButton
{
    public void Render() => Console.WriteLine("Rendering Windows Button...");
}

public class WindowsTextBox : ITextBox
{
    public void Render() => Console.WriteLine("Rendering Windows TextBox...");
}

// MacOS用户界面组件
public class MacOSButton : IButton
{
    public void Render() => Console.WriteLine("Rendering MacOS Button...");
}

public class MacOSTextBox : ITextBox
{
    public void Render() => Console.WriteLine("Rendering MacOS TextBox...");
}

// 抽象工厂接口
public interface IUIComponentFactory
{
    IButton CreateButton();
    ITextBox CreateTextBox();
}

// Windows用户界面组件工厂
public class WindowsUIComponentFactory : IUIComponentFactory
{
    public IButton CreateButton() => new WindowsButton();
    public ITextBox CreateTextBox() => new WindowsTextBox();
}

// MacOS用户界面组件工厂
public class MacOSUIComponentFactory : IUIComponentFactory
{
    public IButton CreateButton() => new MacOSButton();
    public ITextBox CreateTextBox() => new MacOSTextBox();
}

// 配置类
public class Configuration
{
    public string OS { get; set; }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        Configuration config = new Configuration { OS = "Windows" };

        IUIComponentFactory factory;
        if (config.OS == "Windows")
        {
            factory = new WindowsUIComponentFactory();
        }
        else if (config.OS == "MacOS")
        {
            factory = new MacOSUIComponentFactory();
        }
        else
        {
            throw new ArgumentException("Unsupported operating system");
        }

        IButton button = factory.CreateButton();
        ITextBox textBox = factory.CreateTextBox();

        button.Render();
        textBox.Render();
    }
}

解释

  1. 用户界面组件接口 (IButtonITextBox):定义了渲染按钮和文本框的方法。
  2. 具体用户界面组件 (WindowsButton、WindowsTextBox、MacOSButton、MacOSTextBox):实现了具体的按钮和文本框渲染逻辑。
  3. 抽象工厂接口 (IUIComponentFactory):定义了创建按钮和文本框的方法。
  4. 具体工厂类 (WindowsUIComponentFactoryMacOSUIComponentFactory):实现了具体的按钮和文本框创建逻辑。
  5. 配置类 (Configuration):用于存储操作系统的配置信息。
  6. 客户端代码 (Program):根据配置信息选择合适的工厂类,并使用工厂类创建具体的用户界面组件,然后调用其渲染方法。

2. 数据库操作框架

假设我们正在开发一个数据库操作框架,需要根据不同的数据库类型创建不同的数据访问对象。

csharp 复制代码
// 数据访问接口
public interface IDbConnection
{
    void Connect();
    void Disconnect();
}

public interface IDbCommand
{
    void Execute();
}

// MySQL数据库操作
public class MySqlConnection : IDbConnection
{
    public void Connect() => Console.WriteLine("Connecting to MySQL database...");
    public void Disconnect() => Console.WriteLine("Disconnecting from MySQL database...");
}

public class MySqlCommand : IDbCommand
{
    public void Execute() => Console.WriteLine("Executing MySQL command...");
}

// SQL Server数据库操作
public class SqlServerConnection : IDbConnection
{
    public void Connect() => Console.WriteLine("Connecting to SQL Server database...");
    public void Disconnect() => Console.WriteLine("Disconnecting from SQL Server database...");
}

public class SqlCommand : IDbCommand
{
    public void Execute() => Console.WriteLine("Executing SQL Server command...");
}

// 抽象工厂接口
public interface IDbFactory
{
    IDbConnection CreateConnection();
    IDbCommand CreateCommand();
}

// MySQL数据库工厂
public class MySqlDbFactory : IDbFactory
{
    public IDbConnection CreateConnection() => new MySqlConnection();
    public IDbCommand CreateCommand() => new MySqlCommand();
}

// SQL Server数据库工厂
public class SqlServerDbFactory : IDbFactory
{
    public IDbConnection CreateConnection() => new SqlServerConnection();
    public IDbCommand CreateCommand() => new SqlCommand();
}

// 配置类
public class Configuration
{
    public string DatabaseType { get; set; }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        Configuration config = new Configuration { DatabaseType = "MySQL" };

        IDbFactory factory;
        if (config.DatabaseType == "MySQL")
        {
            factory = new MySqlDbFactory();
        }
        else if (config.DatabaseType == "SQLServer")
        {
            factory = new SqlServerDbFactory();
        }
        else
        {
            throw new ArgumentException("Unsupported database type");
        }

        IDbConnection connection = factory.CreateConnection();
        IDbCommand command = factory.CreateCommand();

        connection.Connect();
        command.Execute();
        connection.Disconnect();
    }
}

总结

抽象工厂模式通过提供一个创建一系列相关或相互依赖对象的接口,使得对象的创建更加灵活和一致。虽然它增加了系统的复杂度,但在需要创建多个相关对象的场景中,抽象工厂模式能够显著提高代码的可维护性和扩展性。

相关推荐
程序研3 小时前
JAVA之外观模式
java·设计模式
军训猫猫头4 小时前
52.this.DataContext = new UserViewModel(); C#例子 WPF例子
开发语言·c#·wpf
博一波5 小时前
【设计模式-行为型】观察者模式
观察者模式·设计模式
等一场春雨5 小时前
Java设计模式 十二 享元模式 (Flyweight Pattern)
java·设计模式·享元模式
AI+程序员在路上8 小时前
C#调用c++dll的两种方法(静态方法和动态方法)
c++·microsoft·c#
rolt10 小时前
电梯系统的UML文档07
设计模式·产品经理·架构师·uml
数据的世界0110 小时前
C#中的语句
服务器·c#
装疯迷窍_A10 小时前
ARCGIS国土超级工具集1.3更新说明
arcgis·c#·插件·变更调查·尖锐角·狭长
秋月的私语13 小时前
c#实现当捕获异常时自动重启程序
运维·c#
等一场春雨14 小时前
Java设计模式 十 装饰模式 (Decorator Pattern)
java·设计模式·装饰器模式