找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

697

积分

0

好友

87

主题
发表于 6 小时前 | 查看: 0| 回复: 0

本文将深入浅出地讲解C#中的建造者模式,从核心概念、适用场景到两种经典实现方式,通过完整的代码示例帮你彻底掌握这一创建型设计模式。

C# 建造者模式图解

一、建造者模式是什么?

建造者模式是一种创建型设计模式,其核心思想是将一个复杂对象的构建过程与其最终表示分离,使得同样的构建流程可以创建出不同的产品。

说得更直白一些,它就像你去定制一杯咖啡:

  • 基础的构建流程是固定的(选择杯型 → 选择基底 → 选择配料 → 选择奶/糖);
  • 但每一步都有多个选项(大杯/中杯、美式/拿铁、焦糖/巧克力);
  • 最终,由“建造者”根据你的选择,一步步组装出你想要的那杯咖啡。

那么,什么样的场景适合使用建造者模式呢?

  • 当对象包含多个组成部分,且构建步骤固定,但每个步骤的实现可以灵活变化时。
  • 为了规避因参数过多导致的“伸缩构造函数”反模式。
  • 需要根据不同的配置,生成一系列复杂对象时(例如:组装不同配置的电脑、创建不同规格的订单)。

二、C# 建造者模式的核心角色

一个标准的建造者模式通常包含以下几个角色:

  1. 产品(Product):最终要构建的复杂对象(例如:咖啡、电脑)。
  2. 抽象建造者(IBuilder):定义构建产品所需的所有步骤(通常是一个接口或抽象类)。
  3. 具体建造者(ConcreteBuilder):实现抽象建造者定义的各个步骤,负责构建和组装产品的各个部件,生成具体产品的变体。
  4. 指挥者(Director):负责控制构建流程,按特定顺序调用建造者的方法(此角色可选,客户端也可直接调用建造者)。

三、完整代码实现(咖啡定制案例)

下面我们用一个“定制咖啡”的生动例子,来完整实现一次建造者模式。

1. 产品类(Coffee)

首先,定义我们要构建的复杂对象——咖啡。

/// <summary>
/// 产品:咖啡(复杂对象)
/// </summary>
public class Coffee
{
    // 咖啡属性
    public string CupSize { get; set; } // 杯型:大杯/中杯/小杯
    public string BaseType { get; set; } // 基底:美式/拿铁/卡布奇诺
    public string Topping { get; set; } // 配料:焦糖/巧克力/无
    public string MilkType { get; set; } // 奶型:全脂/脱脂/无糖奶

    // 展示咖啡配置
    public void ShowCoffeeInfo()
    {
        Console.WriteLine($"定制咖啡:{CupSize} | {BaseType} | 配料:{Topping} | 奶型:{MilkType}");
    }
}

2. 抽象建造者(ICoffeeBuilder)

定义构建咖啡必须遵循的步骤。

/// <summary>
/// 抽象建造者:定义构建咖啡的所有步骤
/// </summary>
public interface ICoffeeBuilder
{
    void BuildCupSize(); // 构建杯型
    void BuildBaseType(); // 构建基底
    void BuildTopping(); // 构建配料
    void BuildMilkType(); // 构建奶型
    Coffee GetCoffee(); // 获取最终产品
}

3. 具体建造者(两种咖啡变体)

实现抽象接口,创建两种具体的咖啡配置。

/// <summary>
/// 具体建造者1:焦糖拿铁(大杯、全脂奶)
/// </summary>
public class CaramelLatteBuilder : ICoffeeBuilder
{
    private Coffee _coffee = new Coffee();

    public void BuildCupSize()
    {
        _coffee.CupSize = "大杯";
    }

    public void BuildBaseType()
    {
        _coffee.BaseType = "拿铁";
    }

    public void BuildTopping()
    {
        _coffee.Topping = "焦糖";
    }

    public void BuildMilkType()
    {
        _coffee.MilkType = "全脂奶";
    }

    public Coffee GetCoffee()
    {
        return _coffee;
    }
}

/// <summary>
/// 具体建造者2:无糖美式(中杯、无奶)
/// </summary>
public class SugarFreeAmericanoBuilder : ICoffeeBuilder
{
    private Coffee _coffee = new Coffee();

    public void BuildCupSize()
    {
        _coffee.CupSize = "中杯";
    }

    public void BuildBaseType()
    {
        _coffee.BaseType = "美式";
    }

    public void BuildTopping()
    {
        _coffee.Topping = "无";
    }

    public void BuildMilkType()
    {
        _coffee.MilkType = "无奶";
    }

    public Coffee GetCoffee()
    {
        return _coffee;
    }
}

4. 指挥者(控制构建流程)

指挥者定义了构建一杯咖啡的标准流程。

/// <summary>
/// 指挥者:负责控制构建流程(固定步骤)
/// </summary>
public class CoffeeDirector
{
    // 构建咖啡的统一流程
    public Coffee ConstructCoffee(ICoffeeBuilder builder)
    {
        builder.BuildCupSize();
        builder.BuildBaseType();
        builder.BuildTopping();
        builder.BuildMilkType();
        return builder.GetCoffee();
    }
}

5. 客户端调用(使用建造者模式)

最后,看看客户端如何通过指挥者和建造者来获得产品。

class Program
{
    static void Main(string[] args)
    {
        // 1. 创建指挥者
        var director = new CoffeeDirector();

        // 2. 构建焦糖拿铁
        ICoffeeBuilder latteBuilder = new CaramelLatteBuilder();
        Coffee caramelLatte = director.ConstructCoffee(latteBuilder);
        caramelLatte.ShowCoffeeInfo(); // 输出:定制咖啡:大杯 | 拿铁 | 配料:焦糖 | 奶型:全脂奶

        // 3. 构建无糖美式
        ICoffeeBuilder americanoBuilder = new SugarFreeAmericanoBuilder();
        Coffee sugarFreeAmericano = director.ConstructCoffee(americanoBuilder);
        sugarFreeAmericano.ShowCoffeeInfo(); // 输出:定制咖啡:中杯 | 美式 | 配料:无 | 奶型:无奶
    }
}

四、简化版建造者(无指挥者,链式调用)

在实际的C#开发中,我们更常使用一种简化版的链式建造者,它无需指挥者,特别适合用来构建DTO或实体类,能有效避免因参数过多而产生的“伸缩构造函数”。

/// <summary>
/// 简化版链式建造者(常用)
/// </summary>
public class CoffeeBuilder
{
    private Coffee _coffee = new Coffee();

    // 链式设置杯型
    public CoffeeBuilder WithCupSize(string cupSize)
    {
        _coffee.CupSize = cupSize;
        return this;
    }

    // 链式设置基底
    public CoffeeBuilder WithBaseType(string baseType)
    {
        _coffee.BaseType = baseType;
        return this;
    }

    // 链式设置配料
    public CoffeeBuilder WithTopping(string topping)
    {
        _coffee.Topping = topping;
        return this;
    }

    // 链式设置奶型
    public CoffeeBuilder WithMilkType(string milkType)
    {
        _coffee.MilkType = milkType;
        return this;
    }

    // 构建最终产品
    public Coffee Build()
    {
        return _coffee;
    }
}

// 客户端调用(链式构建)
class Program
{
    static void Main(string[] args)
    {
        // 自定义构建一杯咖啡
        Coffee myCoffee = new CoffeeBuilder()
            .WithCupSize("小杯")
            .WithBaseType("卡布奇诺")
            .WithTopping("巧克力")
            .WithMilkType("脱脂奶")
            .Build();

        myCoffee.ShowCoffeeInfo(); // 输出:定制咖啡:小杯 | 卡布奇诺 | 配料:巧克力 | 奶型:脱脂奶
    }
}

总结

  1. 核心目的:建造者模式的核心价值在于解耦了复杂对象的“构建过程”和“最终表示”,使得同一套构建流程能够创建出不同的产品变体。
  2. 两种实现方式
    • 标准模式(抽象建造者 + 具体建造者 + 指挥者):适用于构建流程固定、产品变体繁多的场景,是设计模式的经典实现。
    • 链式建造者(无指挥者):在C#开发中更为常用,它通过返回this实现链式调用,非常适合灵活地定制对象属性,完美解决了“伸缩构造函数”带来的困扰。
  3. 适用场景:当对象属性众多、配置灵活多变,或者需要统一和复用构建流程时,建造者模式是你的优先选择。

最后简单对比一下:工厂模式关注的是“创建整个对象”,而建造者模式则更关注“如何一步步地构建对象的各个细节”。如果你想深入学习更多关于.NET技术栈和架构设计的知识,欢迎到云栈社区与其他开发者交流探讨。




上一篇:硬件工程师如何通过“复刻-改进”模式实现快速技术成长
下一篇:GitHub官方Monaspace字体评测:专为代码优化的纹理修复与连字设计
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-24 17:28 , Processed in 0.236264 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表