修改后的生成器模式是什么?

2022-09-03 06:19:50

GoF的原始Builder模式和Joshua Bloch的“修订后的GoF Builder模式”有什么区别?


答案 1

GoF 模式侧重于抽象构造步骤,以便通过改变构建器可以获得不同的结果,而“修订后的构建器”则针对的是多个构造函数添加的不必要复杂性问题。因此,GoF模式更多地是关于抽象的,而修改后的模式更多的是关于简单性(IMO)。

看看 http://en.wikipedia.org/wiki/Builder_patternhttp://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html 的例子,它应该很清楚。


答案 2

请注意Mikko的答案Hansen的例子有一些问题 - 或者至少与Bloch的版本不同,尽管我认为Bloch的版本更优越。

具体说来:

首先,的字段是在 构造函数中设置的,而不是在构造函数中设置的,因此不是(也不能是)。 据说是不可变的,但没有什么可以阻止另一个程序员在以后添加二传手。WidgetBuilder.build()WidgetfinalWidget

其次,汉森构建方法中的注释说“预创建验证在这里”。布洛赫(EJ 2ed. p.15)说:

在将参数从生成器复制到对象后,必须检查 [不变量],并在对象字段而不是生成器字段上检查它们(项目 39)。

如果你翻到第39项(第185页),你会看到理由:

[This] 保护类在检查参数和复制参数之间的“漏洞窗口”期间防止另一个线程对参数进行更改。

中的字段是不可变的,不需要任何防御性复制,但是,只要坚持正确的模式,以防有人出现并添加一个或数组或一些可变的模式,这是更安全的。(它还可以防止另一个线程在调用中修改 ,但这是一个非常狭窄的安全窗口,所以最好只是确保 s 不在线程之间共享。WidgetDateCollectionBuilderbuild()Builder

一个更像布洛赫的版本是:

public class Widget {
    public static class Builder {
        private String name;
        private String model;
        private String serialNumber;
        private double price;
        private String manufacturer;

        public Builder( String name, double price ) {
            this.name = name;
            this.price = price;
        }

        public Widget build() {
            Widget result = new Widget(this);

            // *Post*-creation validation here

            return result;
        }

        public Builder manufacturer( String value ) {
            this.manufacturer = value;
            return this;
        }

        public Builder serialNumber( String value ) {
            this.serialNumber = value;
            return this;
        }

        public Builder model( String value ) {
            this.model = value;
            return this;
        }
    }

    private final String name;
    private final String model;
    private final String serialNumber;
    private final double price;
    private final String manufacturer;

    /**
     * Creates an immutable widget instance.
     */
    private Widget( Builder b ) {
        this.name = b.name;
        this.price = b.price;
        this.model = b.model;
        this.serialNumber = b.serialNumber;
        this.manufacturer = b.manufacturer;
    }

    // ... etc. ...
}

所有字段现在都已,并且所有字段都在构造后进行验证。Widgetfinal


推荐