DotNETWeekly-io / DotNetWeekly

DotNet weekly newsletter
MIT License
198 stars 3 forks source link

【文章推荐】掌握 Fluent Builder Design #665

Closed gaufung closed 2 weeks ago

gaufung commented 1 month ago

https://www.youtube.com/watch?v=qCIr30WxJQw&ab_channel=MilanJovanovi%C4%87

gaufung commented 3 weeks ago

Builder Pattern 是一种设计模式,通常有下面的特点

ASP.NET Core 中依赖注入中包含了很多这样的设计,这里一个简单的 C# 例子来展示这个模式实现

var order = OrderBuilder.Empty.SetName("Order 1")
                .WithNumber(1)
                .ShipTo(s => s.City("São Paulo").ZipCode("01310-100"))
                .Build();

public class Order {
  public string Name { get; set; }

  public int Number{ get; set; }

  public Street Street { get; set; }
}

public class Street {
  public string City { get; set; }

  public string ZipCode { get; set; }
}

public class OrderBuilder {
  public static OrderBuilder Empty => new OrderBuilder();

  private OrderBuilder() {}

  private string _name;
  private int _number;

  private StreetBuilder _streetBuilder = StreetBuilder.Empty;

  public OrderBuilder SetName(string name) {
    _name = name;
    return this;
  }

  public OrderBuilder WithNumber(int number) {
    _number = number;
    return this;
  }

  public OrderBuilder ShipTo(Action<StreetBuilder> buildStreet) {
    buildStreet(_streetBuilder);
    return this;
  }

  public Order Build() {
    return new Order{Name = _name, Number = _number,
                     Street = _streetBuilder.Build()};
  }
}

public class StreetBuilder {
  public static StreetBuilder Empty => new StreetBuilder();

  private StreetBuilder() {}
  private string _city;
  private string _zipCode;

  public StreetBuilder City(string city) {
    _city = city;
    return this;
  }

  public StreetBuilder ZipCode(string zipCode) {
    _zipCode = zipCode;
    return this;
  }

  public Street Build() { return new Street{City = _city, ZipCode = _zipCode}; }
}

这里的 Order 是目标的对象,但是我们增加了 OrderBuilder 类,它的 SetNameWithNumber 两个方法是保存相关属性,而 Street 是另外个一个对象,所以我们有构建了 StreetBuilder 类,在 OrderBuilder 中使用接受一个 Action<StreetBuilder> 委托来创建这个属性,最后的 Build 方法把记录的数据和委托构造出一个 Order 对象。