It's natural if you think calmly, but I thought about it for a moment, so as a memo ...
I'll omit the Getter
/ Setter
, but there is a Square
class that has vertical and horizontal lengths in the fields.
Square.java
public class Square {
private int width;
private int height;
}
If you make it possible to set the value using Builder
and create a class that returns the area at the end, it will be as follows.
SquareBuilder.java
public class SquareBuilder {
public static class Builder {
Square square = new Square();
public Builder() {}
public Builder width(int width) {
square.setWidth(width);
return this;
}
public Builder height(int height) {
square.setHeight(height);
return this;
}
public int build() {
return square.getWidth() * square.getHeight();
}
}
}
Then, you can find the area like this
Main.java
public class Main {
public static void main(String[] args) {
SquareBuilder.Builder squareBuilder = new SquareBuilder.Builder();
System.out.println("Area is:" + squareBuilder.width(5).height(10).build());
}
}
There is no particular problem so far. : slight_smile:
Next, create a Cube
class that inherits from Square
. (Omit Getter
/ Setter
.)
Cube.java
public class Cube extends Square {
private int depth;
}
Aside from whether the height was depth
...: kissing:
It also inherits Builder
CubeBuilder.java
public class CubeBuilder extends SquareBuilder {
public static class Builder extends SquareBuilder.Builder {
private Cube cube = new Cube();
public Builder() {}
public Builder depth(int depth) {
cube.setDepth(depth);
return this;
}
@Override
public int build() {
return super.build() * cube.getDepth();
}
}
}
Then, you can find the volume like this.
Main.java
public class Main {
public static void main(String[] args) {
CubeBuilder.Builder cubeBuilder = new CubeBuilder.Builder();
System.out.println("Volume is:" + cubeBuilder.depth(2).width(5).height(10).build());
}
}
This code goes through compilation and requires volume, but it's actually a problem.
You have to call depth ()
first to find the volume. : worried:
The reason is that the return values of width ()
and height ()
are of type SquareBuilder.Builder
, so you can't calldepth ()
, which is defined only in CubeBuilder.Builder
. ..
We will use Generics here.
Reference: Subclassing a Java Builder class
SquareBuilder.java
public class SquareBuilder {
public static class Builder<T extends Builder<T>> {
Square square = new Square();
public Builder() {}
public T width(int width) {
square.setWidth(width);
return (T) this;
}
public T height(int height) {
square.setHeight(height);
return (T) this;
}
public int build() {
return square.getWidth() * square.getHeight();
}
}
}
CubeBuilder.java
public class CubeBuilder extends SquareBuilder {
public static class Builder extends SquareBuilder.Builder<Builder> {
private Cube cube = new Cube();
public Builder() {}
public Builder depth(int depth) {
cube.setDepth(depth);
return this;
}
@Override
public int build() {
return super.build() * cube.getDepth();
}
}
}
As a result, the return type of width ()
and height ()
will be a class that inherits SquareBuilder.Builder
instead of SquareBuilder.Builder
, so you need to calldepth ()
first. lose.
Main.java
public class Main {
public static void main(String[] args) {
SquareBuilder.Builder squareBuilder = new SquareBuilder.Builder();
System.out.println("Area is:" + squareBuilder.width(5).height(10).build());
CubeBuilder.Builder cubeBuilder = new CubeBuilder.Builder();
System.out.println("Volume is:" + cubeBuilder.width(5).height(10).depth(2).build());
}
}
However, I feel a little uncomfortable because there is a Warning. : mask:
It's a program that puts values in POJOs with a lot of fields and outputs them in JSON format, so it became troublesome to put values in Setter
one by one, and I was addicted to using Builder
.
In this example, the area cannot be calculated, but Warning can be eliminated by making SquareBuilder
an abstract class.
SquareBuilder.java
public class SquareBuilder {
public abstract static class Builder<T extends Builder<T>> {
Square square = new Square();
public Builder() {}
public abstract T getThis();
public T width(int width) {
square.setWidth(width);
return getThis();
}
public T height(int height) {
square.setHeight(height);
return getThis();
}
public int build() {
return square.getWidth() * square.getHeight();
}
}
}
CubeBuilder.java
public class CubeBuilder extends SquareBuilder {
public static class Builder extends SquareBuilder.Builder<Builder> {
private Cube cube = new Cube();
public Builder() {}
@Override
public Builder getThis() {
return this;
}
public Builder depth(int depth) {
cube.setDepth(depth);
return this;
}
@Override
public int build() {
return super.build() * cube.getDepth();
}
}
}
Recommended Posts