Featured image of post ความแตกต่างทางตรรกะระหว่าง bind(), singleton(), scoped() และ instance() ใน Laravel คืออะไร? สามารถใช้งานในสถานการณ์ใดได้บ้าง?

ความแตกต่างทางตรรกะระหว่าง bind(), singleton(), scoped() และ instance() ใน Laravel คืออะไร? สามารถใช้งานในสถานการณ์ใดได้บ้าง?

ความแตกต่างทางตรรกะระหว่าง bind(), singleton(), scoped() และ instance() ใน Laravel คืออะไร? สามารถใช้งานในสถานการณ์ใดได้บ้าง?

การเปรียบเทียบวิธีการ Binding Object ใน Laravel Service Container

วิธีการ bind() singleton() scoped() instance()
คำอธิบาย สร้างอินสแตนซ์ใหม่ทุกครั้งที่มีการเรียกใช้ (Resolved) สร้างอินสแตนซ์เพียงครั้งเดียว และส่งคืนอินสแตนซ์เดิมในคำขอครั้งต่อไป สร้างอินสแตนซ์เพียงครั้งเดียวภายในแต่ละรอบการทำงานของคำขอ/งาน (Request/Job Lifecycle) และจะถูกล้างหลังจากคำขอสิ้นสุดลง ผูก (Bind) อินสแตนซ์ที่มีอยู่แล้วเข้ากับคอนเทนเนอร์ และส่งคืนอินสแตนซ์นั้นทุกครั้งที่มีการเรียกใช้
ข้อดี - ได้อินสแตนซ์ใหม่สำหรับทุกคำขอ ไม่มีปัญหาเรื่องการแชร์สถานะ (State Sharing)
- การใช้หน่วยความจำสะอาดหมดจด
- เหมาะสำหรับตรรกะที่ต้องการสถานะที่เป็นอิสระ
- สามารถกำหนดค่าเฉพาะสำหรับแต่ละคำขอได้
- ประหยัดทรัพยากรระบบโดยสร้างอินสแตนซ์เพียงครั้งเดียว
- รับประกันความสม่ำเสมอของสถานะ
- เหมาะสำหรับการแชร์การกำหนดค่าและทรัพยากร
- ประสิทธิภาพดีกว่าในสถานการณ์ที่มีการทำงานพร้อมกันสูง (High Concurrency)
- สมดุลระหว่างการใช้หน่วยความจำและการแชร์สถานะ
- แชร์สถานะภายในคำขอเดียวกัน แต่แยกจากกันระหว่างคำขอ
- เหมาะสำหรับสถานการณ์ Web Request
- ควบคุมจังหวะการสร้างอินสแตนซ์ได้อย่างสมบูรณ์
- สามารถกำหนดค่าสถานะของอินสแตนซ์ล่วงหน้าได้
- เหมาะสำหรับบริการที่ต้องการการกำหนดค่าเฉพาะ
ข้อเสีย - ต้องใช้ทรัพยากรระบบมากขึ้นในการสร้างอินสแตนซ์ซ้ำๆ
- อาจส่งผลกระทบต่อประสิทธิภาพภายใต้การทำงานพร้อมกันสูง
- ไม่เหมาะสำหรับสถานการณ์ที่ต้องการแชร์สถานะ
- อาจทำให้เกิดปัญหาด้านประสิทธิภาพเนื่องจากมีการสร้างอินสแตนซ์ใหม่ทุกครั้ง
- สถานะที่แชร์อาจนำไปสู่บั๊กที่ติดตามได้ยาก
- ไม่เหมาะสำหรับสถานการณ์ที่ต้องการสถานะที่เป็นอิสระ
- การใช้หน่วยความจำจะยังคงอยู่จนกว่าโปรแกรมจะสิ้นสุด
- การทดสอบต้องใส่ใจเป็นพิเศษในการรีเซ็ตสถานะ
- หากอินสแตนซ์นั้นถือสถานะไว้อาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด
- อาจทำให้เกิดปัญหาในงานที่ใช้เวลานาน (Long-running tasks)
- จำเป็นต้องเข้าใจวงจรชีวิตของคำขอ (Request Lifecycle)
- ไม่เหมาะสำหรับคำสั่ง CLI
- ยืดหยุ่นน้อยกว่า
- ไม่สามารถปรับการกำหนดค่าอินสแตนซ์แบบไดนามิกได้
- อาจใช้หน่วยความจำเมื่อเริ่มต้น
- ไม่เหมาะสำหรับกรณีที่ต้องการ Lazy Loading หรือหลายอินสแตนซ์
กรณีการใช้งาน สำหรับบริการที่ใช้งานระยะสั้นหรือคลาสที่ต้องการสถานะที่เป็นอิสระ สำหรับบริการที่แชร์ทั่วโลก เช่น Logger หรือ Configuration Manager สำหรับบริการที่ต้องการรักษาสถานะภายในคำขอ แต่ไม่ต้องการข้ามคำขอ เช่น การเชื่อมต่อฐานข้อมูล เมื่อคุณมีอินสแตนซ์อยู่แล้วและต้องการนำกลับมาใช้ใหม่ เช่น อ็อบเจกต์การกำหนดค่าที่แชร์
ตัวอย่าง เมื่อคุณมีคลาส Product และต้องการสร้างอินสแตนซ์ Product ใหม่ทุกครั้งที่มีการขอข้อมูลผลิตภัณฑ์ที่แตกต่างกัน เมื่อคุณมีคลาส Logger และต้องการให้การดำเนินการเขียนบันทึกทั้งหมดใช้อินสแตนซ์เดียวกันเพื่อรักษาความสม่ำเสมอ เมื่อคุณมีคลาส ShoppingCart และต้องการแชร์สถานะตะกร้าสินค้าภายในคำขอเดียวกัน เมื่อคุณมีคลาส DatabaseConfig และต้องการตั้งค่าพารามิเตอร์การเชื่อมต่อเมื่อแอปพลิเคชันเริ่มทำงาน

ตัวอย่าง

การใช้ bind()

$this->app->bind('Product', function () {
 return new Product();
});

ทุกครั้งที่เรียก app('Product') จะส่งคืนอินสแตนซ์ Product ใหม่

การใช้ singleton()

$this->app->singleton('Logger', function () {
 return new Logger();
});

ทุกครั้งที่เรียก app('Logger') จะส่งคืนอินสแตนซ์ Logger ตัวเดิม

การใช้ scoped()

$this->app->scoped(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

แชร์อินสแตนซ์เดียวกันภายในวงจรชีวิตของคำขอเดียวกัน คำขอที่แตกต่างกันจะสร้างอินสแตนซ์ใหม่

การใช้ instance()


$service = new Transistor(new PodcastParser);
 
$this->app->instance(Transistor::class, $service);

ผูกอินสแตนซ์ที่มีอยู่แล้วเข้ากับคอนเทนเนอร์โดยตรง

สรุป

ปัจจุบัน Laravel สามารถนำไปใช้ในสถานการณ์ต่างๆ มากมาย เช่น Web Request, CLI Command, Queue Job, Console Command เป็นต้น

ดังนั้น ในการเลือกใช้วิธีการ Binding แบบใด คุณต้องพิจารณาความต้องการของบริการในสถานการณ์ต่างๆ และพิจารณาว่าคุณจำเป็นต้องแชร์สถานะหรือการกำหนดค่าหรือไม่

Reference

All rights reserved,未經允許不得隨意轉載
ถูกสร้างด้วย Hugo
ธีม Stack ออกแบบโดย Jimmy