• 作者:老汪软件技巧
  • 发表时间:2024-09-29 10:01
  • 浏览量:

在本系列的第一部分中,我们探讨了两种基础的创建型设计模式:单例模式(Singleton) 和 工厂方法模式(Factory Method)。这些模式帮助管理 C# 中的对象创建,提供了将对象创建过程与业务逻辑解耦的方法。

现在,让我们深入探讨三种更高级的创建型设计模式:抽象工厂模式(Abstract Factory)、建造者模式(Builder) 和 原型模式(Prototype),这些模式解决了更复杂的对象创建场景。

抽象工厂模式(Abstract Factory)什么是抽象工厂?

抽象工厂模式为创建一组相关或依赖的对象提供了一个接口,而无需指定它们的具体类。它允许客户端使用工厂方法创建对象,但具体的实例化过程由子类决定。

现实生活类比

想象一个工厂生产不同风格的家具,比如现代风格或维多利亚风格。每种风格都有一系列相关的产品,例如椅子、沙发和桌子。抽象工厂将定义一个家具产品家族,而具体工厂(如 ModernFactory 和 VictorianFactory)则负责根据选择的风格创建正确的家具类型。

它解决了什么问题?

在系统需要创建一组相关且必须协同工作的对象时,抽象工厂模式非常有用。例如,UI 工具包通常需要创建特定平台的控件(如按钮和窗口),这些控件需要彼此兼容。

如何在 C# 中实现

以下是一个使用抽象工厂模式的 C# 示例,展示如何为不同平台创建按钮和窗口的产品家族:

// 抽象产品
public interface IButton
{
    void Render();
}
public interface IWindow
{
    void Render();
}
// Windows 的具体产品
public class WindowsButton : IButton
{
    public void Render() => Console.WriteLine("渲染 Windows 按钮");
}
public class WindowsWindow : IWindow
{
    public void Render() => Console.WriteLine("渲染 Windows 窗口");
}
// MacOS 的具体产品
public class MacButton : IButton
{
    public void Render() => Console.WriteLine("渲染 Mac 按钮");
}
public class MacWindow : IWindow
{
    public void Render() => Console.WriteLine("渲染 Mac 窗口");
}
// 抽象工厂
public interface IGUIFactory
{
    IButton CreateButton();
    IWindow CreateWindow();
}
// 具体工厂
public class WindowsFactory : IGUIFactory
{
    public IButton CreateButton() => new WindowsButton();
    public IWindow CreateWindow() => new WindowsWindow();
}
public class MacFactory : IGUIFactory
{
    public IButton CreateButton() => new MacButton();
    public IWindow CreateWindow() => new MacWindow();
}
// 客户端代码
public class Application
{
    private IButton _button;
    private IWindow _window;
    public Application(IGUIFactory factory)
    {
        _button = factory.CreateButton();
        _window = factory.CreateWindow();
    }
    public void Render()
    {
        _button.Render();
        _window.Render();
    }
}
// 使用示例
var windowsApp = new Application(new WindowsFactory());
windowsApp.Render();
var macApp = new Application(new MacFactory());
macApp.Render();

何时使用

抽象工厂模式非常适合需要创建一组相关对象的场景,比如 UI 组件,这些组件必须能够无缝协同工作。

常见陷阱现实案例

跨平台 UI 开发通常使用抽象工厂模式,以确保像按钮和窗口这样的组件与它们的环境(例如 Windows 或 macOS)兼容。

建造者模式(Builder)什么是建造者模式?

建造者模式用于一步步构建复杂对象。与其他创建型模式不同,建造者不要求产品具有通用接口,因此可以灵活地构建不同的对象表现形式。

现实生活类比

想象一下建造一座房子。房子由许多部分组成(例如,地基、墙壁、屋顶),不同类型的房子可能需要以不同方式组装这些部分。建造者模式允许逐步构建对象,提供了灵活性来控制对象的创建过程。

它解决了什么问题?

建造者模式简化了需要多个步骤才能构建的复杂对象。与其通过一个包含大量参数的构造函数来创建对象,建造者模式使构造过程更具可读性和可管理性。

如何在 C# 中实现

以下是一个使用建造者模式来构建房子的 C# 示例:

// 产品类
public class House
{
    public string Walls { get; set; }
    public string Roof { get; set; }
    public string Foundation { get; set; }
    
    public void ShowDetails()
    {
        Console.WriteLine($"这是一座有 {Walls}, {Roof}, 和 {Foundation} 的房子");
    }
}
// 生成器接口
public interface IHouseBuilder
{
    void BuildWalls();
    void BuildRoof();
    void BuildFoundation();
    House GetHouse();
}
// 石头房子的具体生成器
public class StoneHouseBuilder : IHouseBuilder
{
    private House _house = new House();
    public void BuildWalls() => _house.Walls = "石墙";
    public void BuildRoof() => _house.Roof = "石屋顶";
    public void BuildFoundation() => _house.Foundation = "混凝土地基";
    public House GetHouse() => _house;
}
// 导演类
public class HouseDirector
{
    private IHouseBuilder _builder;
    public HouseDirector(IHouseBuilder builder)
    {
        _builder = builder;
    }
    public House ConstructHouse()
    {
        _builder.BuildWalls();
        _builder.BuildRoof();
        _builder.BuildFoundation();
        return _builder.GetHouse();
    }
}
// 使用示例
var stoneBuilder = new StoneHouseBuilder();
var director = new HouseDirector(stoneBuilder);
var house = director.ConstructHouse();
house.ShowDetails();

何时使用

当创建一个对象需要多个步骤或配置时,建造者模式特别有用,使构造过程更易于管理。

常见陷阱现实案例

建造者模式通常用于构建复杂的配置,例如软件中的文档或大型表单。

原型模式(Prototype)什么是原型模式?

原型模式通过复制现有对象(即原型)来创建新对象。这个模式在对象创建成本高或过程复杂时特别有用,避免了重复创建新实例的麻烦。

_抽象工厂模式的优缺点_抽象工厂模式类图

现实生活类比

克隆生物是原型模式的一个恰当类比。与其从头开始创建一个新生物,不如通过克隆现有生物来生成一个相似的个体。

它解决了什么问题?

原型模式解决了对象创建成本昂贵或不合适直接实例化的场景,通过复制现有对象快速生成新实例。

如何在 C# 中实现

以下是一个使用原型模式进行浅拷贝和深拷贝的 C# 示例:

public class PrototypeExample
{
    public string Name { get; set; }
    public List<string> Data { get; set; }
    public PrototypeExample ShallowCopy() => (PrototypeExample)this.MemberwiseClone();
    public PrototypeExample DeepCopy()
    {
        var clone = (PrototypeExample)this.MemberwiseClone();
        clone.Data = new List<string>(this.Data);
        return clone;
    }
}

何时使用

当对象创建成本较高,或者频繁需要基于现有对象创建新对象时,适合使用原型模式。

常见陷阱现实案例

游戏开发中,原型模式经常用于克隆游戏实体,例如 NPC 或敌人,而不需要从头开始重新创建它们。

创建模式的比较模式使用案例示例

单例

确保一个类只有一个实例。

日志服务,配置

工厂方法

将对象创建与业务逻辑解耦。

创建动物(狗、猫等)

抽象工厂

提供创建相关对象家族的接口。

跨平台UI元素

建造者

逐步构建复杂对象。

建造房屋或配置

原型

通过复制现有对象来创建新对象。

游戏中的克隆实体

创建模式的常见陷阱结论

选择合适的创建模式对于在C#中创建灵活、可维护和可扩展的应用程序至关重要。了解每种模式的优缺点将帮助您在项目中做出明智的决定。尝试不同的模式,以掌握其在实际场景中的使用。

参考文献与进一步阅读