From 0218ba16ec95f5bb2cb479959bddcac128d985fb Mon Sep 17 00:00:00 2001 From: ChaerinYu Date: Sun, 20 Mar 2022 10:30:37 +0900 Subject: [PATCH 1/2] create: [ETC/DesignPattern] Builder Pattern (#77) --- ETC/builder_pattern.md | 131 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 ETC/builder_pattern.md diff --git a/ETC/builder_pattern.md b/ETC/builder_pattern.md new file mode 100644 index 0000000..7f5ea64 --- /dev/null +++ b/ETC/builder_pattern.md @@ -0,0 +1,131 @@ + +# Builder Pattern 빌더 패턴 +* 생성자 오버로딩 +* 클래스에 생성자(`constructor`) 인자가 많다면 `builder pattern`을 사용하면 좋다. +* 인스턴스 생성할 때, 생성자만을 통해서 생성하는데 어려움이 있어 고안된 패턴 + +
+
+ +``` java +public class User { + private int userId; // 필수 + private String name; // 필수 + private int age; // 선택 +} + ``` +* 빌더 패턴을 사용하지 않는 경우, 필수인자만 받는 생성자를 만들고 선택적으로 받는 생성자를 만드면 된다. + * `overloading`을 통한 생성자 여러 개 만들기 + 👉 점층적 생성자 패턴 (`telescoping constructor pattern`) + +
+ +### 점층적 생성자 패턴 (telescoping constructor pattern) + +``` java +public class User { + private String userId; // 필수 + private String name; // 필수 + private int age; // 선택 + + public User(String userId, String name) { + this.userId = userId; + this.name = name; + } + + public User(String userId, String name, int age) { + this(userId, name); + this.age = age; + } +} + ``` +* 코드가 길어지고 지저분해진다. + +``` java +User user = new User("user_12345", "사용자"); +User user = new User("challenger", "챌린지", 11); +``` +* 순서를 알고 있어야 한다. +* 생성자 인자가 많은 경우 알아보기가 힘들다. + +
+ +이러한 단점을 보완하기 위해 `setter` 메소드를 사용한 `자바 빈(Bean) 패턴`이 고안되었다. + +### 자바 빈(Bean) 패턴 + +``` java +User user = new User(); +user.setUserId("challenger"); +user.setName("챌린지"); +user.setAge(11); +``` +* 객체 생성하기 쉬우며 읽기 좋다. +* 한 줄 작성으로 객체 생성이 끝나지 않아 객체 일관성(consistency)이 일시적으로 깨지는 위험 발생 + 👉 thread간 공유 가능한 상태가 존재하기 때문 + + +
+ +생성자 패턴과 자바 빈 패턴의 장점을 결합한 것이 바로 빌더 패턴(`builder pattern`)이다. + +### 빌더 패턴 (Builder Pattern) + +* 필요한 객체를 직접 생성하는 대신 먼저 *필수 인자*들을 생성자에 전부 전달하여 빌더 객체를 만든다. +* *선택 인자*는 가독성이 좋은 코드로 인자를 넘길 수 있다. +* 객체 일관성이 유지된다. + +``` java +public class User { + private String userId; // 필수 + private String name; // 필수 + private int age; // 선택 + + // static 클래스인 Builder 존재 + public static class Builder { + private String userId = "challenger"; + private String name = "챌린지"; + private int age = 11; + + // 필수 값인 userId와 name 인자를 가진 생성자 + public User(String userId, String name) { + this.userId = userId; + this.name = name; + } + + public Builder age(int age) { + this.age = age; + return this; + } + + public User build() { + return new User(this); + } + } + + public User(Builder builder) { + this.userId = builder.userId; + this.name = builder.name; + this.age = builder.age; + } + + public static void main(String[] args) { + User user = new Builder("challenger", "챌린지") + .age(11) + .build(); + } +} +``` + +* User 클래스에 setter 는 없이 getter 만 갖고 있으며 public 생성자가 따로 없다. + 👉 User 객체를 얻기 위해서는 오직 Builder 클래스를 통해서만 가능하다. +* 빌더 패턴은 만들려는 객체를 바로 만들지 않고 클라이언트가 **빌더(생성자 또는 static 팩토리)에 필수적인 매개변수**를 주면서 +호출해 `Builder` 객체를 얻는다. +* 그 다음 빌더 객체가 제공하는 **`setter`와 비슷한 메소드를 사용해서 부가적인 필드**를 채운다. +* 최종적으로 **`build`라는 메소드를 호출**해서 만드려는 **객체를 생성**한다. + + +
+
+ +[참고](https://devlog-wjdrbs96.tistory.com/207) \ No newline at end of file From b6e7fad4afc4cc8e21265d080e8cb34abbe5b506 Mon Sep 17 00:00:00 2001 From: ChaerinYu Date: Sun, 20 Mar 2022 20:54:16 +0900 Subject: [PATCH 2/2] update: [DesignPattern] builder pattern update (#77) --- ETC/builder_pattern.md | 126 ++++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 39 deletions(-) diff --git a/ETC/builder_pattern.md b/ETC/builder_pattern.md index 7f5ea64..f1dec83 100644 --- a/ETC/builder_pattern.md +++ b/ETC/builder_pattern.md @@ -1,6 +1,5 @@ # Builder Pattern 빌더 패턴 -* 생성자 오버로딩 * 클래스에 생성자(`constructor`) 인자가 많다면 `builder pattern`을 사용하면 좋다. * 인스턴스 생성할 때, 생성자만을 통해서 생성하는데 어려움이 있어 고안된 패턴 @@ -9,9 +8,11 @@ ``` java public class User { - private int userId; // 필수 - private String name; // 필수 - private int age; // 선택 + private int userId; // 필수 + private String name; // 필수 + private int age; // 선택 + private String address; // 선택 + private String email; // 선택 } ``` * 빌더 패턴을 사용하지 않는 경우, 필수인자만 받는 생성자를 만들고 선택적으로 받는 생성자를 만드면 된다. @@ -24,9 +25,11 @@ public class User { ``` java public class User { - private String userId; // 필수 - private String name; // 필수 - private int age; // 선택 + private String userId; // 필수 + private String name; // 필수 + private int age; // 선택 + private String address; // 선택 + private String email; // 선택 public User(String userId, String name) { this.userId = userId; @@ -37,6 +40,16 @@ public class User { this(userId, name); this.age = age; } + + public User(String userId, String name, int age, String address) { + this(userId, name, age); + this.address = address; + } + + public User(String userId, String name, int age, String address, String email) { + this(userId, name, age, address); + this.email = email; + } } ``` * 코드가 길어지고 지저분해진다. @@ -44,6 +57,8 @@ public class User { ``` java User user = new User("user_12345", "사용자"); User user = new User("challenger", "챌린지", 11); +User user = new User("challenger", "챌린지", 11, "경기도"); +User user = new User("challenger", "챌린지", 11, "경기도", "abc@def.com"); ``` * 순서를 알고 있어야 한다. * 생성자 인자가 많은 경우 알아보기가 힘들다. @@ -59,6 +74,8 @@ User user = new User(); user.setUserId("challenger"); user.setName("챌린지"); user.setAge(11); +user.setAddress("경기도"); +user.setEmail("abc@def.com"); ``` * 객체 생성하기 쉬우며 읽기 좋다. * 한 줄 작성으로 객체 생성이 끝나지 않아 객체 일관성(consistency)이 일시적으로 깨지는 위험 발생 @@ -77,41 +94,60 @@ user.setAge(11); ``` java public class User { - private String userId; // 필수 - private String name; // 필수 - private int age; // 선택 - - // static 클래스인 Builder 존재 - public static class Builder { - private String userId = "challenger"; - private String name = "챌린지"; - private int age = 11; - - // 필수 값인 userId와 name 인자를 가진 생성자 - public User(String userId, String name) { - this.userId = userId; - this.name = name; - } - - public Builder age(int age) { - this.age = age; - return this; - } - - public User build() { - return new User(this); - } - } - - public User(Builder builder) { - this.userId = builder.userId; - this.name = builder.name; - this.age = builder.age; - } + private String userId; // 필수 + private String name; // 필수 + private int age; // 선택 + private String address; // 선택 + private String email; // 선택 + + // static 클래스인 Builder 존재 - 내부에 빌더 클래스로 선언할 경우 꼭 static으로 선언! + public static class Builder { + private String userId = "challenger"; + private String name = "챌린지"; + private int age = 11; + private String address = "경기도"; + private String email = "abc@def.com"; + + // 필수 값인 userId와 name 인자를 가진 생성자 + public User(String userId, String name) { + this.userId = userId; + this.name = name; + } + + public Builder age(int age) { + this.age = age; + return this; + } + + public Builder address(String address) { + this.address = address; + return this; + } + + public Builder email(String email) { + this.email = email; + return this; + } + + // 빌더 클래스 반환 + public User build() { + return new User(this); + } + } + + public User(Builder builder) { + this.userId = builder.userId; + this.name = builder.name; + this.age = builder.age; + this.address = builder.address; + this.email = builder.email; + } public static void main(String[] args) { User user = new Builder("challenger", "챌린지") .age(11) + .address("경기도") + .email("abc@def.com") .build(); } } @@ -124,8 +160,20 @@ public class User { * 그 다음 빌더 객체가 제공하는 **`setter`와 비슷한 메소드를 사용해서 부가적인 필드**를 채운다. * 최종적으로 **`build`라는 메소드를 호출**해서 만드려는 **객체를 생성**한다. +

+ +> ## ✔ 정리 +> ### Builder Pattern의 장점 +> +> - 불필요한 생성자를 만들지 않고 객체를 만든다. +> 👉 필요한 데이터만 설정할 수 있다. +> - 데이터 순서 상관없이 객체를 만들 수 있다. +> 👉 매개변수에 따라 다른객체 만들 수 있다. 유연하다. +> - 사용자가 봤을 때 명시적이고 가독성이 좋다. +> - 변경 가능성 최소화할 수 있다.

-[참고](https://devlog-wjdrbs96.tistory.com/207) \ No newline at end of file +[참고1](https://devlog-wjdrbs96.tistory.com/207) +[참고2](https://mangkyu.tistory.com/163) \ No newline at end of file