안녕하세요.
이번 포스팅은 상태가 Optional할 때 생길 수 있는 문제점을 알아보고 대처 방안 중 하나인 빌더 패턴에 대해서 알아보겠습니다.
빌더 패턴이란 생성 패턴 중에 하나로, 생성 패턴은 인스턴스를 만드는 절차를 추상화하는 패턴입니다.
public class ChessGameEntity {
private long id;
private String name;
private String password;
private boolean isOn;
private String teamValueOfTurn;
}
객체를 생성할 때 모든 상태 값을 알고있지 않거나, 해당 객체가 모든 상태 값을 가지지 않아도 될 때가 있습니다.
클래스는 상태가 optional하다면 어떻게 생성해야할까요?
ChessGameEntity chessGameEntity = new ChessGameEntity(1L, "juri", "1234", null, null);
생성자에는 순서가 정해져 있기 때문에 매번 생성자의 argument 순서를 고려해야합니다.
만약 알고 있는 생성자가 매번 변한다면, 굉장히 귀찮은 일이 될 것 입니다.
public ChessGameEntity(final long id, final String name, final String password, final boolean isOn,
final String teamValueOfTurn) {
this.id = id;
this.name = name;
this.password = password;
this.isOn = isOn;
this.teamValueOfTurn = teamValueOfTurn;
}
public ChessGameEntity(final String name, final String password, final ChessGame chessGame) {
this.name = name;
this.password = password;
this.isOn = chessGame.isOn();
this.teamValueOfTurn = chessGame.getTurn().getNow().getValue();
}
public ChessGameEntity(final long id, final boolean isOn, final Turn turn) {
this.id = id;
this.isOn = isOn;
this.teamValueOfTurn = turn.getNow().getValue();
}
public ChessGameEntity(final long id, final String password) {
this.id = id;
this.password = password;
}
public ChessGameEntity(final long id, final boolean isOn) {
this.id = id;
this.isOn = isOn;
}
알고 있는 상태마다 생성자를 만들 수 있습니다.
하지만 이 경우, 부생성자의 수가 생성자를 사용하기 힘들 정도로 많다면 어떤 생성자를 쓸지 고민하는 시간이 더 많이 생길 것 입니다.
또한 객체를 생성할 때 외부 의존적인 특성을 가지게 됩니다.
결국 2가지 방법의 단점은 가독성입니다.
어떤 값을 순서에 맞게 넣는지 알 수 없기 때문입니다.
아래 예제를 통해 해결 방안인 빌더 패턴의 사용법을 알아봅시다.
public class ChessGameEntityBuilder {
private long id;
private String name;
private String password;
private boolean power;
private String teamValueOfTurn;
}
생성할 클래스와 상태가 같은 Builder 클래스를 생성합니다.
public ChessGameEntityBuilder setId(final long id) {
this.id = id;
return this;
}
public ChessGameEntityBuilder setName(final String name) {
this.name = name;
return this;
}
public ChessGameEntityBuilder setPassword(final String password) {
this.password = password;
return this;
}
public ChessGameEntityBuilder setPower(final boolean power) {
this.power = power;
return this;
}
public ChessGameEntityBuilder setTeamValueOfTurn(final String teamValueOfTurn) {
this.teamValueOfTurn = teamValueOfTurn;
return this;
}
public ChessGameEntity build() {
return new ChessGameEntity(id, name, password, power, teamValueOfTurn);
}
각 상태 값마다 setter를 만들고, Builder 클래스를 반환하도록 합니다.
그리고 build 메서드를 통해 ChessGameEntity 클래스를 만듭니다.
ChessGameEntity chessGameEntity = new ChessGameEntityBuilder()
.setId(chessGameId)
.setPower(false)
.build();
빌더 패턴을 사용하면 어떤 상태 값을 주입할지 명확하게 알 수 있고, 순서를 신경쓰지 않아도 된다는 장점이 있습니다.
또한 필요한 상태 값만 주입할 수 있다는 장점이 있습니다.