Builder Design Pattern使用它的真正优势是什么

时间:2016-05-20 04:29:33

标签: design-patterns

维基百科国家

  

构建器模式是对象创建软件设计模式。   与抽象工厂模式和工厂方法模式不同   其目的是为了实现多态性的目的   构建器模式是找到伸缩构造函数的解决方案   反模式[需要引证]。伸缩式构造器   当对象构造函数参数增加时发生反模式   组合导致指数的构造函数列表。代替   使用众多构造函数,构建器模式使用另一个对象,   一个构建器,它逐步接收每个初始化参数   然后立即返回生成的构造对象。

并给出以下示例

    //Represents a product created by the builder
public class Car
{
    public Car()
    {
    }

    public int Wheels { get; set; }

    public string Colour { get; set; }
}

//The builder abstraction
public interface ICarBuilder
{
    // Adding NotNull attribute to prevent null input argument
    void SetColour([NotNull]string colour);

    // Adding NotNull attribute to prevent null input argument
    void SetWheels([NotNull]int count);

    Car GetResult();
}

//Concrete builder implementation
public class CarBuilder : ICarBuilder
{
    private Car _car;

    public CarBuilder()
    {
        this._car = new Car();
    }

    public void SetColour(string colour)
    {
        this._car.Colour = colour;
    }

    public void SetWheels(int count)
    {
        this._car.Wheels = count;
    }

    public Car GetResult()
    {
        return this._car;
    }
}

//The director
public class CarBuildDirector
{
    public Car Construct()
    {
        CarBuilder builder = new CarBuilder();

        builder.SetColour("Red");
        builder.SetWheels(4);

        return builder.GetResult();
    }
}
  1. 这似乎是一个不必要的重定向。为什么不能使用 CarBuilder()直接初始化一个汽车对象并设置其属性 直接。在这段代码中使用carbuilder的优点是什么 段?
  2. 是构建器模式的意图,仅用于避免伸缩构造器 反模式?如果是这样的话,那似乎是不必要的工作,因为 可以使用getter和setter直接设置属性

2 个答案:

答案 0 :(得分:0)

示例给出的示例未显示构建器模式的真正优势。考虑这样一个类:

public class Demo{
    private Integer i;
    private Short s;
    private String str;
    private Double d;
    private Float f;
    private Boolean b;
    private Byte by;

    public Demo(Integer i, Short s, String str, Double d, Float f, Boolean b, Byte b){
        //setting all members ommited...
    }


    public Demo(Short s, String str, Double d, Float f, Boolean b, Byte by){
        this(null, s, str, d, f, b, by);
    }

    public Demo(Integer i,  String str, Double d, Float f, Boolean b, Byte b){
        this(i, null, str, d, f, b, by);
    }

    public Demo(Integer i){
        this(i, "Very short constructor", null, null, null, null);
    }

}

已经有4个构造函数,可能还有更多。构造函数也委托给" base"构造

但是如果使用构建器模式,则可以删除除一个构造函数之外的所有构造函数。

public class DemoBuilder{
    private Integer i=INTEGER_DEFAULT;
    private Short s = SHORT_DEFAULT;
    private String str=STRING_DEFAULT;
    private Double d=DOUBLE_DEFAULT;
    private Float f=FLOAT_DEFAULT;
    private Boolean b=BOOLEAN_DEFAULT;
    private Byte by=BYTE_DEFAULT;

    public void setStr(String str){
        this.str=str;
    }

    //more setters

    public Demo build(){
        return new Demo(i,s,str,d,f,b,by);
    }
}

现在,您还不需要文档来识别不同构造函数及其参数的语义。你有一个构建器,每个setter都有一个有意义的名字。在我的示例中只有setStr,但在一个更实际的示例中,就像setServerName

总而言之:

  1. 在某些情况下,您需要在对象创建过程中需要大量参数。我记得一个班级需要4个策略和几个参数的情况。由于它们不会在对象生命周期中发生变化,因此它们在最终成员之前是明显的候选者。但构造函数看起来像public MyClass(IStrategy doBefore, IStrategy doAfter, IStrategy doInBetween, IStrategy doOnException, String name, int priority, MyEnum anotherEnumConstant)。即使它只有一个构造函数,构建器也简化了对象的创建。
  2. 构建器模式还将参数顺序转换为命名方法。这是一个更清洁的方法。

答案 1 :(得分:0)

谨防维基百科文章中的无源语句。如果您注意,请在摘录中[citation needed]的位置,工具提示说:

  

需要可靠的来源。 Go4模式描述了不同的目的   对于模式。

事实上,原始模式更像维基百科文章中的几行定义:

  

Builder设计模式的目的是分离   从其表示构造复杂对象。通过这样做   相同的构建过程可以创建不同的表示

Go4书明确指出,Builder的目的是具有不同的构造风格。它涉及一个抽象的Builder,它定义了如何构建最终对象的合同,以及具体的Builder子类。本书中的所有示例都包括抽象类和具体子类,例如StandardMazeBuilderCountingMazeBuilder等。您提供的维基百科代码示例不具备,这使得它与IMO的相关性降低。