자바에서 객체를 만드는 대표적인 2가지 방법이라 하면
Setter 메서드로 생성하기
생성자로 생성하기
를 꼽을 수 있다.
그럼 두 방법의 문제점은 무엇일까?
Setter의 문제점
1. 일관성 문제
public class User {
private String id;
private String pw;
private String name;
public void setId(String id) {
this.id = id;
}
public void setPw(String pw) {
this.pw = pw;
}
public void setName(String name) {
this.name = name;
}
}
회원가입을 할 때 user의 정보를 받아오는 클래스이다.
id , pw, name 이 회원가입에 필수라고 가정하고
User user = new User();
user.setId("abc");
이런식으로 id만 setter로 값을 설정하면 컴파일 시점에는 문제없으나
데이터베이스에서는 나머지 pw, name이 필수값으로 등록되어 있으니 오류를 발생시킨다.
즉 일관성이 불안정한 상태에서 사용이 가능하다는 문제점이 있다.
또 다른 일관성 문제로 setter의 접근자는 public으로 선언되어야 한다는 점에서 찾을 수 있는데
public void setId(String id)
이렇게 public 접근자를 가지면 어디서든 객체의 값에 접근과 변경이 가능하다.
이는 일관성을 지키기 힘들게 한다.
그렇다고 만약 일관성을 지키기 위해 해당 필드를 final키워드로 변경을 못하게 강제 한다면 언제 어디서든 값을 변경할 수 있는
setter와 final이 서로 상충하게 되므로 컴파일 오류를 불러일으킨다.
2.의도 파악의 문제
setter는 값을 초기화하거나 바꿀 때 둘다 쓸 수 있다.
이러한 점이 의도를 파악하기 어렵게 하는데
user.setId("abc");
위의 setter가 id를 초기 설정 하는 것인지 변경 하는 것인지 알수가 없다.
따라서 이럴 경우 따로 id 변경 메소드를 작성하는 것이 해결책이 될 수 있다.
따라서 setter 메서드의 사용은 지양 할 필요가 있다
생성자의 문제점
우선 생성자는
User user = new User("abc","123","아무개");
이렇게 하나의 메서드를 통해서 객체 생성과 값을 설정하여
완성된 객체를 반환하므로 일관성을 지킬 수 있다.
하지만 이러한 점이 문제점이 될 수 있다.
1.매개변수가 많을 때
public class User {
private String id;
private String pw;
private String name;
private Integer age;
private String hobby;
private String job;
public User(String id, String pw, String name, Integer age, String hobby, String job) {
this.id = id;
this.pw = pw;
this.name = name;
this.age = age;
this.hobby = hobby;
this.job = job;
}
}
이렇게 user의 필드가 많아짐에 따라 생성자도 매개변수를 많이 받는데
우선 id와 pw , name으로만 회원가입을 하고 나머지 정보는 나중에 입력하고 싶으면
User user = new User("abc","123","아무개",null,null,null);
이렇게 설정하지 않는 값들을 null로 채워야하는 번거로움이 있으며
변수 값을 어느 위치에 넣어야 할지 알기 어려워진다.
그렇다고 생성자 메소드를 경우에 따라 오버로딩을 통해 여러개를 생성하면 코드량이 많아질 수 있다.
또 만약
public User(String id, String pw, String name, String hobby) {
this.id = id;
this.pw = pw;
this.name = name;
this.hobby = hobby;
}
public User(String id, String pw, String name, String job) {
this.id = id;
this.pw = pw;
this.name = name;
this.job = job;
}
이런식으로 생성자 메소드를 오버로딩 하고 싶다면
오버로딩 원칙에 위배가 되므로 생성이 불가능하다.
따라서 생성자에 매개변수가 많다면 빌더를 고려해야 한다.
그렇다면 빌더 패턴이란 무엇일까?
복잡한 객체들을 단계별로 구축할 수 있는 생성 디자인 패턴이며, 한마디로 객체를 잘 만들게 해주는 도구이다.
빌더 클래스를 만드는 법은 아래와 같다.
public class User {
private String id;
private String pw;
private String name;
private User(String id, String pw, String name) { //private로 하면 빌더를 통해서만 객체 생성하도록 함
this.id = id;
this.pw = pw;
this.name = name;
}
public static class Builder{ //정적 내부 클래스 생성
//세팅 할 각 필드 생성
private String id;
private String pw;
private String name;
//각각 필드 값을 설정하는 메서드를 생성, 자기자신(빌더 객체)를 반환해야 함
public Builder id(String id){
this.id = id;
return this;
}
public Builder pw(String pw){
this.pw = pw;
return this;
}
public Builder name(String name){
this.name =name;
return this;
}
public User build(){
return new User(id,pw,name);
}
}
}
그리고 사용은 아래와 같다.
User user = new User.Builder().name("아무개")
.id("abc").pw("123").build();
또 만약 필요한 필드 값만 설정을 한다고 하면
User user = new User.Builder()
.id("abc").pw("123").build();
이처럼 필요한 값만 설정을 하면, 나머지 값은 자동으로 null로 설정이 된다.
빌더는 어디에 어떤값을 세팅하는지 명확하게 알고 사용이 가능해 가독성이 높으며
마지막에 build()를 호출해야 객체로써 활용이 가능하므로 일관성을 지킬 수 있다.
'Java&SpringBoot' 카테고리의 다른 글
쓰레드의 동기화 volatile (Java,기초) (0) | 2024.03.13 |
---|---|
NPE, Optional (Java,기초) (0) | 2024.03.08 |
오류와 예외처리(Java,기초) (0) | 2024.03.07 |