什么时候使用生成器模式 ❓

如果一个类中有很多的属性,为了避免构造函数的参数列表过长,影响代码的可读性喝易用性,我们可以通过构造函数配合set() 方法来解决,但是如果存在下面情况中的任意一种,我们就要考虑使用生成器模式了。

  • 我们把类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数又出现参数列表很长的问题。如果把必填属性通过set()方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。

  • 如果类的属性之间有一定的依赖关系或者约束条件,我们就继续使用构造函数配合Set ()方法的设计思路,那这些依赖关系喝约束条件的校验逻辑就无处安放了

  • 如果我们希望创建不可变对象,也就是说,对象在创建还之后,就不能再修改内部的属性值,要实现这个功能,我们就不能在类中暴露 set()方法,构造函数配合set() 方法来设置属性值的方式就不适用了。

除此之外,我们对比一下工厂模式喝创建者模式的区别,工厂模式是用来床架你不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种 类型的对象,创建者模式是用来创建一种类型的复杂对象,可以通过不同的可选参数,“定制化”地创建不同的对象。

代码示例


public class BuildPattern_Geek
{
  static void Main()
  {
      var doll = new DollBild()   
          .SetColor("green")
          .SetQuality(222)
          .SetPrice(200)
          .Build(); // 返回Doll对象
  }
}

class Doll
{
    public string Color { get; }
    public int Quality { get; }
    public int Price { get; }
    public float CostPerformance { get; }

    public Doll(DollBild builder)
    {
        Color = builder.Color;
        Quality = builder.Quality;
        Price = builder.Price;
        CostPerformance = builder.CostPerformance;
    }
}

class DollBild
{
    private const string DefaultColor = "yellow";
    private const int DefaultPrice = 99;

    private string _color = DefaultColor;
    private int _quality = -1;
    private int _price = DefaultPrice;
    private float _costPerformance;

    public string Color
    {
        get => _color;
        set => _color = value ?? DefaultColor;
    }

    public int Quality
    {
        get => _quality;
        set => _quality = value > 0 ? value : throw new ArgumentException("质量必须大于0");
    }

    public int Price
    {
        get => _price;
        set => _price = value > 0 ? value : DefaultPrice;
    }

    public float CostPerformance => _costPerformance;

    public DollBild SetColor(string color)
    {
        Color = color;
        return this;
    }

    public DollBild SetQuality(int quality)
    {
        Quality = quality;
        return this;
    }

    public DollBild SetPrice(int price)
    {
        Price = price;
        return this;
    }

    public Doll Build()
    {
        if (_quality <= 0)
            throw new InvalidOperationException("质量未设置!");

        _costPerformance = (float)_price / _quality;
        return new Doll(this);
    }
}