当前位置: 首页 > 面试题库 >

如何改善建造者模式?

夏立果
2023-03-14
问题内容

动机

最近,我在寻找一种无需向构造函数传递大量参数即可初始化复杂对象的方法。我使用了构建器模式进行了尝试,但是我不喜欢这样的事实,即如果我真的设置了所有需要的值,就无法在编译时检查。

传统建筑图案

当我使用构建器模式创建Complex对象时,创建起来更“类型安全”,因为更容易了解参数的用途:

new ComplexBuilder()
        .setFirst( "first" )
        .setSecond( "second" )
        .setThird( "third" )
        ...
        .build();

但是现在我有一个问题,我很容易错过一个重要的参数。我可以在build()方法中检查它,但这仅在运行时进行。如果我错过了一些东西,在编译时没有什么警告我的。

增强的构建器模式

现在,我的想法是创建一个生成器,如果我错过了所需的参数,它会“提醒我”。我的第一次尝试如下所示:

public class Complex {
    private String m_first;
    private String m_second;
    private String m_third;

    private Complex() {}

    public static class ComplexBuilder {
        private Complex m_complex;

        public ComplexBuilder() {
            m_complex = new Complex();
        }

        public Builder2 setFirst( String first ) {
            m_complex.m_first = first;
            return new Builder2();
        }

        public class Builder2 {
            private Builder2() {}
            Builder3 setSecond( String second ) {
                m_complex.m_second = second;
                return new Builder3();
            }
        }

        public class Builder3 {
            private Builder3() {}
            Builder4 setThird( String third ) {
                m_complex.m_third = third;
                return new Builder4();
            }
        }

        public class Builder4 {
            private Builder4() {}
            Complex build() {
                return m_complex;
            }
        }
    }
}

如您所见,构建器类的每个setter返回一个不同的内部构建器类。每个内部构建器类仅提供一个setter方法,最后一个仅提供一个build()方法。

现在,对象的构造再次如下所示:

new ComplexBuilder()
    .setFirst( "first" )
    .setSecond( "second" )
    .setThird( "third" )
    .build();

…但是无法忘记所需的参数。编译器不会接受它。

可选参数

如果我有可选参数,我将使用最后一个内部构建器类Builder4来像“传统”构建器一样设置它们,并返回自身。

  • 这是众所周知的模式吗?它有一个特殊的名字吗?
  • 您看到任何陷阱吗?
  • 在减少代码行的意义上,您有什么想法可以改善实现吗?

问题答案:

不,这不是新的。您实际上在做什么,就是通过扩展标准的构建器模式以支持分支来创建一种DSL,这是确保构建器不会对实际对象产生一组冲突设置的极好方法。

我个人认为这是对构建器模式的一个很好的扩展,您可以用它来做各种有趣的事情,例如,在工作中,我们为某些数据完整性测试提供了DSL构建器,使我们可以执行assertMachine().usesElectricity().and().makesGrindingNoises().whenTurnedOn();。好的,也许不是最好的例子,但我想你明白了。



 类似资料:
  • 主要内容:介绍,实现,Item.java,Packing.java,Wrapper.java,Bottle.java,Burger.java,ColdDrink.java,VegBurger.java,ChickenBurger.java,Coke.java,Pepsi.java,Meal.java,MealBuilder.java,BuilderPatternDemo.java,相关文章建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模

  • 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。 介绍 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的

  • 简介 生成器模式是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。 范例 /** "Product" */ class Pizza { private String dough = ""; private String sauce = ""; private String topping = ""

  • 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。 介绍 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的

  • 处理DOM时,我们常常想要去动态的构建新的元素--这是一个会让我们希望构建的元素最终所包含的标签,属性和参数的复杂性有所增长的过程。 定义复杂的元素时需要特别的小心,特别是如果我们想要在我们元素标签的字面意义上(这可能会乱成一团)拥有足够的灵活性,或者取而代之去获得更多面向对象路线的可读性。我们需要一种为我们构建复杂DOM对象的机制,它独立于为我们提供这种灵活性的对象本身,而这正是建造者模式为我们

  • 建造者模式 如果说前面的工厂模式是对接口进行抽象化处理,那么建造者模式更像是对流程本身的一种抽象化处理。这话怎么理解呢?大家可以听我慢慢到来。以前买电脑的时候,大家都喜欢自己组装机器。一方面可以满足自己的个性化需求,另外一方面也可以在价格上得到很多实惠。但是电脑是由很多部分组成的,每个厂家都只负责其中的一部分,而且相同的组件也有很多的品牌可以从中选择。这对于我们消费者来说当然非常有利,那么应该怎么