如何改进构建器模式? [英] How to improve the builder pattern?

查看:16
本文介绍了如何改进构建器模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Recently I searched for a way to initialize a complex object without passing a lot of parameter to the constructor. I tried it with the builder pattern, but I don't like the fact, that I'm not able to check at compile time if I really set all needed values.

当我使用构建器模式创建我的 Complex 对象时,创建更类型安全",因为更容易看到参数的用途:

When I use the builder pattern to create my Complex object, the creation is more "typesafe", because it's easier to see what an argument is used for:

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

但现在我遇到了一个问题,我很容易错过一个重要的参数.我可以在 build() 方法中检查它,但这只是在运行时.在编译时,如果我错过了什么,没有任何警告我.

But now I have the problem, that I can easily miss an important parameter. I can check for it inside the build() method, but that is only at runtime. At compile time there is nothing that warns me, if I missed something.

现在我的想法是创建一个构建器,如果我错过了一个需要的参数,它会提醒"我.我的第一次尝试看起来像这样:

Now my idea was to create a builder, that "reminds" me if I missed a needed parameter. My first try looks like this:

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() 方法.

As you can see, each setter of the builder class returns a different internal builder class. Each internal builder class provides exactly one setter method and the last one provides only a build() method.

现在对象的构造再次看起来像这样:

Now the construction of an object again looks like this:

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

...但是没有办法忘记一个需要的参数.编译器不会接受它.

...but there is no way to forget a needed parameter. The compiler wouldn't accept it.

如果我有可选参数,我会使用最后一个内部构建器类 Builder4 来设置它们,就像传统"构建器所做的那样,返回自身.

If I had optional parameters, I would use the last internal builder class Builder4 to set them like a "traditional" builder does, returning itself.

  • 这是众所周知的模式吗?它有什么特殊的名字吗?
  • 您是否发现任何陷阱?
  • 您是否有任何改进实现的想法 - 在代码行更少的意义上?

推荐答案

不,这并不新鲜.你实际上在做的是通过扩展标准构建器来创建一种 DSL支持分支的模式,这是确保构建器不会为实际对象生成一组冲突设置的绝佳方式.

No, it's not new. What you're actually doing there is creating a sort of a DSL by extending the standard builder pattern to support branches which is among other things an excellent way to make sure the builder doesn't produce a set of conflicting settings to the actual object.

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

Personally I think this is a great extension to builder pattern and you can do all sorts of interesting things with it, for example at work we have DSL builders for some of our data integrity tests which allow us to do things like assertMachine().usesElectricity().and().makesGrindingNoises().whenTurnedOn();. OK, maybe not the best possible example but I think you get the point.

这篇关于如何改进构建器模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆