调整Builder模式以进行方法调用

Ash*_*dal 6 java methods design-patterns builder effective-java

这是尝试从Effective Java 2nd Edition中仔细理解ITEM 40:设计方法签名的一部分.

建议改进方法签名可读性的一个目的是瞄准四个或更少的参数.建议使用多种技术管理较长的参数列表,其中一种技术如下:

结合前两个方面的第三种技术是使Builder模式(第2项)从对象构造适应方法调用.如果你有一个包含许多参数的方法,特别是如果它们中的一些是可选的,那么定义一个代表所有参数的对象并允许客户端对该对象进行多次"setter"调用是有益的.它设置单个参数或小的相关组.一旦设置了所需的参数,客户端就会调用对象的"执行"方法,该方法对参数进行任何最终有效性检查并执行实际计算.

我熟悉Builder模式,因为它用于对象构造,但我不确定我是否正确理解了如何使其适应方法调用.

这是我到目前为止:(
我试图改进方法的方法调用move)

public class Space {

    public static class Builder {
        // Required parameters
        private final int x;
        private final int y;
        private final int z;

        // optional params
        private long time = 0;

        public Builder(int x, int y, int z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public Builder time(long val) {
            time = val;
            return this;
        }

        public void move() {
            if (x == 0 || y == 0 || z == 0) {
                throw new IllegalArgumentException("Cannot move to the centre of the universe");
            }

            // Do the actual work here
        }
    }

//  public void move(int x, int y, int z, long time) {
//      // Do the work here
//  }

    public static void main(String[] args) {
        new Builder(1, 1, -1).time(1234).move();
    }
}
Run Code Online (Sandbox Code Playgroud)

我对Joshua Bloch的建议的解释是否正确?

bn.*_*bn. 1

我已经使用我想要实例化的类中定义的接口完成了 Builder 模式的具体化。

有关此内容和相关“双向构建器”的额外信息,请参阅此处:http://www.javaworld.com/javaworld/jw-01-2004/jw-0102-toolbox.html ?page=3

我会做类似以下的事情;虽然这对于 3 个必填字段来说可能有些过大,但它对于在考虑每个必填字段的同时构建更大的对象非常有帮助。

public Class Space
{    
    public interface Builder
    {
        public Space build();
        public int x();
        public int y();
        public int z();
    }

    // Build a complete Space object accounting for every field. 
    public Space(Space.Builder spaceBuilder)
    {
        this.x = spaceBuilder.x();
        this.y = spaceBuilder.y();
        this.z = spaceBuilder.z();
        this.time = builder.time();
    }

    // Might not be necessar if you update time when you update x, y, and z
     public Builder time(long val)
     {
            time = val;
            return this;
     }

     public void move()
     {
        // ...
     }

    public static void main(String[] args)
    {
        new Builder()
        {   
            @Override
            public Space build(){ return new Space(this);}

            @Override
            public int x(){ return 1;}

            @Override
            public int y{ return 1;}

            @Override int z{ return -1;}
        }.build().time(1234).move();
    }
}
Run Code Online (Sandbox Code Playgroud)