รูปแบบ Builder กับ Fluent API
สร้างออบเจ็กต์ซับซ้อนทีละขั้นด้วย fluent builder เพื่อหลีกเลี่ยงตัวสร้างที่มีพารามิเตอร์ต่อเนื่องจำนวนมาก
รูปแบบ Builder กับ Fluent API เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
ปัญหาตัวสร้างแบบยืดขยาย
เมื่อคลาสมีพารามิเตอร์เสริมจำนวนมาก ตัวสร้างจะเพิ่มจำนวนขึ้นเรื่อย ๆ เช่น 2 พารามิเตอร์, 3 พารามิเตอร์, 4 พารามิเตอร์ รูปแบบ Builder แก้ปัญหานี้ด้วย API การกำหนดค่าทีละขั้นแบบต่อเนื่อง
// Without builder — hard to read:
Pizza p = new Pizza("large", "thin", true, false, true, false, "mozzarella");โครงสร้าง Builder พื้นฐาน
สร้างคลาส Builder ซ้อนแบบสแตติก คลาสภายนอกจะมีตัวสร้างแบบ private ที่รับ Builder แต่ละเซตเตอร์ใน Builder จะส่งคืน this เพื่อให้เรียกต่อเนื่องกันได้
public final class Pizza {
private final String size, crustType, cheese;
private final boolean extraSauce, pepperoni;
private Pizza(Builder b) {
this.size = b.size; this.crustType = b.crustType;
this.cheese = b.cheese; this.extraSauce = b.extraSauce;
this.pepperoni = b.pepperoni;
}
public static class Builder {
private final String size;
private String crustType = "regular", cheese = "mozzarella";
private boolean extraSauce, pepperoni;
public Builder(String size) { this.size = size; }
public Builder crustType(String c) { this.crustType = c; return this; }
public Builder cheese(String c) { this.cheese = c; return this; }
public Builder extraSauce() { this.extraSauce = true; return this; }
public Builder pepperoni() { this.pepperoni = true; return this; }
public Pizza build() { return new Pizza(this); }
}
}การใช้งาน API แบบต่อเนื่อง
โค้ดของ Builder จะอ่านได้เหมือนประโยค พารามิเตอร์ที่จำเป็นจะอยู่ในตัวสร้าง ส่วนพารามิเตอร์เสริมจะเป็นการเรียกเมธอด การเรียก build() ครั้งสุดท้ายจะสร้างออบเจ็กต์ที่แก้ไขไม่ได้
Pizza p = new Pizza.Builder("large")
.crustType("thin")
.extraSauce()
.pepperoni()
.build();
System.out.println(p);การตรวจสอบใน build()
เพิ่มตรรกะการตรวจสอบไว้ภายใน build() ก่อนสร้างออบเจ็กต์ ให้โยน IllegalStateException หรือ IllegalArgumentException เมื่อพบชุดค่าที่ไม่ถูกต้อง
public Pizza build() {
if (size == null || size.isBlank())
throw new IllegalArgumentException("Size required");
if (extraSauce && crustType.equals("stuffed"))
throw new IllegalStateException("No extra sauce on stuffed crust");
return new Pizza(this);
}Builder สำหรับออบเจ็กต์ที่แก้ไขไม่ได้
เนื่องจากคลาสภายนอกถูกสร้างจาก Builder เพียงครั้งเดียว ฟิลด์ทั้งหมดจึงสามารถเป็น final ได้ ทำให้ออบเจ็กต์ผลลัพธ์แก้ไขไม่ได้โดยสมบูรณ์และปลอดภัยต่อเธรด
public final class Address {
private final String street, city, country;
private final String postalCode;
private Address(Builder b) { ... } // all finals
// no setters — immutable!
}Builder แบบเจเนอริกที่มีประเภทของตนเอง
สำหรับลำดับชั้นการสืบทอด ให้ใช้พารามิเตอร์ประเภทเจเนอริกแบบเรียกซ้ำ (SELF extends Builder<SELF>) เพื่อให้ Builder ของคลาสย่อยส่งคืนประเภทของคลาสย่อยจากเมธอดที่เรียกต่อเนื่องกัน
public abstract static class Builder<SELF extends Builder<SELF>> {
String name;
@SuppressWarnings("unchecked")
public SELF name(String n) { this.name = n; return (SELF) this; }
public abstract Vehicle build();
}Lombok @Builder
@Builder ของ Lombok จะสร้างโครงสร้างพื้นฐานของ Builder ทั้งหมดขณะคอมไพล์ ใช้ @Builder.Default สำหรับค่าเริ่มต้นของฟิลด์ และใช้ @Singular สำหรับคอลเลกชัน
@Builder
public class Report {
private final String title;
@Builder.Default private final int pageCount = 1;
@Singular private final List<String> authors;
}
// Usage:
Report r = Report.builder().title("Q4").author("Alice").author("Bob").build();Builder ใน JDK
คลาสจำนวนมากใน JDK ใช้ API รูปแบบ Builder เช่น StringBuilder, HttpRequest.newBuilder(), ProcessBuilder และ Stream.Builder ควรจดจำรูปแบบนี้ไว้
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Accept", "application/json")
.GET()
.build();Builder เทียบกับโรงงาน
ใช้ Builder เมื่อออบเจ็กต์ต้องรับพารามิเตอร์จำนวนมากและต้องกำหนดค่าทีละขั้น ใช้โรงงานเมื่อรูปแบบทั้งหมดเรียบง่ายและสามารถสร้างได้ด้วยการเรียกเพียงครั้งเดียว
Builder สำหรับข้อมูลการทดสอบ
Builder มีประโยชน์อย่างมากในการทดสอบ ให้สร้าง Builder พื้นฐานไว้ในตัวช่วย จากนั้นเขียนทับเฉพาะฟิลด์ที่เกี่ยวข้องกับกรณีทดสอบแต่ละกรณี วิธีนี้ช่วยให้การทดสอบเป็นไปตามหลัก DRY และอ่านง่าย
User defaultUser() { return new User.Builder("test@example.com").name("Test User").build(); }
User adminUser() { return new User.Builder("admin@example.com").name("Admin").role(ADMIN).build(); }ความปลอดภัยต่อเธรด
ตัว Builder เองไม่ปลอดภัยต่อเธรด ดังนั้นอย่าใช้ Builder ร่วมกันระหว่างเธรด ออบเจ็กต์ ผลิตภัณฑ์ ที่สร้างจาก Builder สามารถแก้ไขไม่ได้และปลอดภัยต่อเธรดได้ หากฟิลด์ทั้งหมดเป็น final และไม่มีการใช้ออบเจ็กต์ที่แก้ไขได้ร่วมกัน
ตรวจสอบความเข้าใจอย่างรวดเร็ว
อะไรทำให้เมธอดของ Builder เป็นแบบ "ต่อเนื่อง"
สรุปทบทวน
Builder แก้ปัญหาตัวสร้างแบบยืดขยาย ใช้คลาส Builder ซ้อนแบบสแตติก ส่งคืน this จากเซตเตอร์แต่ละตัว ตรวจสอบค่าใน build() และสร้างออบเจ็กต์ที่แก้ไขไม่ได้ Lombok @Builder ช่วยสร้างโค้ดส่วนที่ซ้ำซ้อนโดยอัตโนมัติ
คำถามที่พบบ่อย
บทเรียน “รูปแบบ Builder กับ Fluent API” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “รูปแบบ Builder กับ Fluent API” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบ Builder กับ Fluent API”
สร้างออบเจ็กต์ซับซ้อนทีละขั้นด้วย fluent builder เพื่อหลีกเลี่ยงตัวสร้างที่มีพารามิเตอร์ต่อเนื่องจำนวนมาก คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “รูปแบบ Builder กับ Fluent API” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- Singleton: การใช้งานที่ปลอดภัยต่อเธรด
- รูปแบบ Factory Method
- Abstract Factory สำหรับตระกูลผลิตภัณฑ์
- รูปแบบ Builder กับ Fluent API