รูปแบบ Builder
สร้างออบเจ็กต์ทีละขั้นตอน
รูปแบบ Builder เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
ทำไมต้องใช้ Builder
Rust ไม่มีอาร์กิวเมนต์ของฟังก์ชันที่ตั้งชื่อหรือเป็นตัวเลือกได้ เมื่อโครงสร้างมีหลายฟิลด์ โดยเฉพาะฟิลด์ที่เป็นตัวเลือก คอนสตรักเตอร์ที่มีพารามิเตอร์ตามตำแหน่งแปดตัวจะอ่านยากและเกิดข้อผิดพลาดได้ง่าย
รูปแบบ builder แก้ปัญหานี้ได้ คุณกำหนดค่าออบเจ็กต์ทีละขั้นด้วยเมธอดที่มีชื่อชัดเจน แล้วเรียก build() ขั้นสุดท้ายเพื่อสร้างค่า โค้ดจึงอ่านต่อเนื่องเหมือนประโยค
โครงสร้างเป้าหมาย
เริ่มจากชนิดข้อมูลที่คุณต้องการสร้างจริง ๆ ในที่นี้การกำหนดค่าเซิร์ฟเวอร์มีโฮสต์ที่จำเป็นต้องระบุ และตัวเลือกเพิ่มเติมอีกหลายรายการ
สังเกตว่าฟิลด์ต่าง ๆ เป็นส่วนตัว เพื่อส่งเสริมให้สร้างค่าผ่าน builder แทนการใช้ลิเทอรัลของโครงสร้าง
pub struct ServerConfig {
host: String,
port: u16,
max_connections: usize,
use_tls: bool,
}ชนิด Builder แยกต่างหาก
แนวทางคลาสสิกคือใช้โครงสร้างตัวที่สอง ซึ่งก็คือ builder โดยจะมีโครงสร้างคล้ายเป้าหมาย แต่เก็บสถานะระหว่างการสร้าง ฟิลด์ที่เป็นตัวเลือกมักเปลี่ยนเป็น Option<T> เพื่อแยกได้ว่า "ยังไม่ได้กำหนด" หรือ "กำหนดไว้อย่างชัดเจนแล้ว"
pub struct ServerConfigBuilder {
host: String,
port: Option<u16>,
max_connections: Option<usize>,
use_tls: bool,
}เริ่มต้น Builder
สร้างคอนสตรักเตอร์ให้ builder โดยรับเฉพาะฟิลด์ที่จำเป็น ทุกตัวเลือกจะเริ่มต้นเป็น None หรือค่าเริ่มต้น
รูปแบบที่ใช้กันทั่วไปคือสร้างเมธอด builder() บนชนิดเป้าหมาย ซึ่งคืนค่า builder
impl ServerConfig {
pub fn builder(host: impl Into<String>) -> ServerConfigBuilder {
ServerConfigBuilder {
host: host.into(),
port: None,
max_connections: None,
use_tls: false,
}
}
}เมธอด Setter รับ self ตามค่า
Setter แต่ละตัวจะใช้ self จนหมด แก้ไขฟิลด์ แล้วคืนค่า self การคืนค่าที่เป็นเจ้าของข้อมูลช่วยให้คุณต่อเรียกเมธอดได้อย่างลื่นไหล
การต่อเมธอดโดยอาศัยความเป็นเจ้าของนี้เป็นรูปแบบ Rust ที่เหมาะสม และช่วยหลีกเลี่ยงปัญหายุ่งยากเกี่ยวกับอายุการใช้งาน
impl ServerConfigBuilder {
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
pub fn use_tls(mut self, yes: bool) -> Self {
self.use_tls = yes;
self
}
}ใช้ค่าเริ่มต้นใน build()
build() ขั้นสุดท้ายจะแปลง builder ให้เป็นชนิดจริง ตรงนี้เองที่คุณเติมค่าเริ่มต้นให้สิ่งที่ยังเป็น None โดยใช้ unwrap_or
impl ServerConfigBuilder {
pub fn build(self) -> ServerConfig {
ServerConfig {
host: self.host,
port: self.port.unwrap_or(8080),
max_connections: self.max_connections.unwrap_or(128),
use_tls: self.use_tls,
}
}
}การสร้างแบบต่อเนื่อง
ตอนนี้ขั้นตอนการสร้างอ่านจากบนลงล่างได้ Required data จะถูกส่งเข้า builder() และการปรับตัวเลือกแต่ละอย่างจะเป็นการเรียกที่มีชื่อชัดเจน
ฟิลด์ที่คุณข้ามไปจะใช้ค่าเริ่มต้นโดยอัตโนมัติ
fn main() {
let cfg = ServerConfig::builder("localhost")
.port(9000)
.use_tls(true)
.build();
println!("{}:{} tls={}", cfg.host, cfg.port, cfg.use_tls);
}ตัวอย่างที่ทำงานได้อย่างสมบูรณ์
นี่คือรูปแบบทั้งหมดที่ย่อรวมเป็นโปรแกรมเดียวซึ่งคุณสามารถเรียกใช้ได้ ตัวอย่างแสดงให้เห็นว่าฟิลด์ที่ข้ามไปจะใช้ค่าเริ่มต้นภายใน build()
struct Config { name: String, retries: u32 }
struct Builder { name: String, retries: Option<u32> }
impl Config {
fn builder(name: &str) -> Builder {
Builder { name: name.to_string(), retries: None }
}
}
impl Builder {
fn retries(mut self, n: u32) -> Self { self.retries = Some(n); self }
fn build(self) -> Config {
Config { name: self.name, retries: self.retries.unwrap_or(3) }
}
}
fn main() {
let c = Config::builder("job").build();
println!("{} retries={}", c.name, c.retries);
}build ที่อาจล้มเหลวด้วย Result
บางครั้งการกำหนดค่าอาจไม่ถูกต้อง เช่น พอร์ตเป็นศูนย์ ให้ build() คืนค่าเป็น Result เพื่อให้ความล้มเหลวในการตรวจสอบปรากฏเป็นข้อผิดพลาดที่กู้คืนได้ แทนที่จะเกิดพานิก
impl ServerConfigBuilder {
pub fn try_build(self) -> Result<ServerConfig, String> {
let port = self.port.unwrap_or(8080);
if port == 0 {
return Err("port must be non-zero".into());
}
Ok(ServerConfig { host: self.host, port,
max_connections: self.max_connections.unwrap_or(128),
use_tls: self.use_tls })
}
}ครেট derive_builder
การเขียน builder ด้วยตนเองซ้ำซาก ครेट derive_builder สามารถสร้าง builder ทั้งหมดจากคำอธิบายกำกับ
คุณใส่คำอธิบายกำกับให้ฟิลด์พร้อมค่าเริ่มต้น แล้วจะได้ FooBuilder ที่สร้างขึ้นโดยอัตโนมัติ พร้อม setter และ build() ที่อาจล้มเหลว โดยไม่ต้องเขียนโค้ดเพิ่มเติม
use derive_builder::Builder;
#[derive(Builder)]
struct Channel {
#[builder(default = "8080")]
port: u16,
name: String,
}Builder แบบเป็นเจ้าของข้อมูลเทียบกับแบบอ้างอิงที่แก้ไขได้
มีอยู่สองรูปแบบ รูปแบบที่เป็นเจ้าของข้อมูลจะใช้ self จนหมดและต่อเมธอดได้เป็นธรรมชาติ ส่วนรูปแบบ &mut self จะคืนค่า &mut Self และช่วยให้แบ่งการสร้างออกเป็นหลายคำสั่งได้โดยไม่ต้องผูกตัวแปรใหม่
รูปแบบที่เป็นเจ้าของข้อมูลพบได้บ่อยกว่าสำหรับการสร้างครั้งเดียว ส่วนรูปแบบที่แก้ไขได้เหมาะกับการกำหนดค่าแบบมีเงื่อนไขในลูป
impl ServerConfigBuilder {
pub fn port_ref(&mut self, port: u16) -> &mut Self {
self.port = Some(port);
self
}
}ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับรูปแบบ builder ที่ใช้ self ซึ่งเป็นเจ้าของข้อมูล
สรุป
รูปแบบ builder ช่วยแก้ข้อจำกัดที่ Rust ไม่มีอาร์กิวเมนต์แบบตัวเลือก ชนิด builder จะเก็บสถานะระหว่างการสร้าง setter จะใช้และคืนค่า self เพื่อให้ต่อเมธอดได้ และ build() จะใช้ค่าเริ่มต้นเพื่อสร้างค่าสุดท้าย
ใช้ Result จาก build() สำหรับการตรวจสอบความถูกต้อง และเลือกใช้ derive_builder เพื่อไม่ต้องเขียนโค้ดซ้ำซาก
คำถามที่พบบ่อย
บทเรียน “รูปแบบ Builder” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “รูปแบบ Builder” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบ Builder”
สร้างออบเจ็กต์ทีละขั้นตอน คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “รูปแบบ Builder” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ