รูปแบบการสร้างสรรค์: Singleton
บทความนี้อธิบายถึงวิธีที่รูปแบบ Singleton บังคับใช้เพียงอินสแตนซ์เดียวของคลาสที่เคยสร้างและมีอยู่ตลอดอายุการใช้งานของแอปพลิเคชัน
มันคืออะไร?
singleton เป็นรูปแบบการออกแบบที่ใช้สร้างอินสแตนซ์ของคลาสเดียว โดยทั่วไปจะใช้รูปแบบ Singleton เมื่อมีหลายตัวอย่างที่ควรมีอยู่เพียงอินสแตนซ์เดียวของคลาสและมีการบังคับใช้ข้อจำกัด ตัวอย่างเช่น แคช เธรดพูล และรีจิสตรีควรมีเพียงอินสแตนซ์เดียว
ทำให้ตัวสร้างเป็นส่วนตัวเพื่อให้แน่ใจว่ามีการสร้างวัตถุคลาสเดียวเท่านั้น ด้วยวิธีนี้ เฉพาะสมาชิกชั้นเรียนเท่านั้นที่สามารถเข้าถึงตัวสร้างส่วนตัวและไม่มีใครอื่น
ในโลกแห่งความเป็นจริง รูปแบบ Singleton ช่วยให้มั่นใจได้ว่าจะมีอินสแตนซ์คลาสเดียวเท่านั้นที่มีอยู่และนำเสนอจุดเข้าถึงทั่วโลก
แผนภาพคลาส
แผนภาพชั้นเรียนประกอบด้วยเอนทิตีเดียวเท่านั้น
ซิงเกิลตัน
ตัวอย่าง
สมมติว่าเราต้องการจำลองเครื่องบินอย่างเป็นทางการของประธานาธิบดีอเมริกันที่ชื่อ Airforce One ในซอฟต์แวร์ของเรา คลาส Singleton เป็นตัวแทนที่เหมาะสมที่สุดสำหรับเอนทิตีที่มีเพียงอินสแตนซ์เดียว
นี่คือรหัสสำหรับคลาสซิงเกิลตันของเรา:
มัลติเธรดและซิงเกิลตัน
รหัสนี้ใช้งานได้ตราบเท่าที่แอปพลิเคชันเป็นแบบเธรดเดียว อย่างไรก็ตาม หากเธรดจำนวนมากเข้าถึงคลาสนี้ มีความเป็นไปได้ที่วัตถุต่างๆ จะถูกสร้างขึ้น
ตัวอย่างเช่น:
- เธรด A เรียกใช้เมธอด
getInstanceและค้นหาonlyInstanceค่าเป็นโมฆะ อย่างไรก็ตาม ก่อนที่มันจะสามารถสร้างอินสแตนซ์ได้ บริบทจะถูกเปลี่ยนออกไป - ตอนนี้เธรด B มาพร้อมและเรียก
getInstanceซึ่งส่งคืนAirforceOneวัตถุ - หากมีกำหนดการเธรด A อีกครั้ง ความเสียหายจะเริ่มต้นขึ้น เธรดผ่านการตรวจสอบเงื่อนไข if-null แล้ว และจะดำเนินการสร้าง
AirforceOneวัตถุใหม่และกำหนดให้onlyInstanceกับ ตอนนี้มีAirforceOneวัตถุสองอย่างที่แตกต่างกันอยู่ในธรรมชาติ อันหนึ่งมีเธรด A และอีกอันมีเธรด B
- ด้วยการเพิ่ม
synchronizedวิธีgetInstance()การนี้ คุณจะได้ความปลอดภัยของเธรด - อีกทางเลือกหนึ่งคือการเริ่มต้นอินสแตนซ์แบบสแตติก การรับประกันว่าจะปลอดภัยต่อเธรด
ตรวจสอบการล็อคสองครั้ง
มีปัญหาสำคัญสองประการเกี่ยวกับวิธีการที่อธิบายไว้ข้างต้น: การซิงโครไนซ์มีราคาแพง และการเริ่มต้นแบบสแตติกจะสร้างออบเจกต์แม้ว่าจะไม่ได้ใช้ในการเรียกใช้แอปพลิเคชันเฉพาะก็ตาม หากการสร้างอ็อบเจกต์มีราคาแพง การกำหนดค่าเริ่มต้นแบบสแตติกอาจทำให้เราสูญเสียประสิทธิภาพการทำงาน
โซลูชันข้างต้นทำเครื่องหมายว่าอินสแตนซ์ซิงเกิลตันมีความผันผวน อย่างไรก็ตาม การปฏิบัติตามระเบียบวิธีของ JVM นี้volatileจะทำงานไม่ถูกต้องสำหรับการล็อกแบบตรวจสอบซ้ำ และคุณจะต้องใช้วิธีอื่นเพื่อสร้างซิงเกิลตันของคุณ
สำนวน การล็อคแบบ ตรวจสอบซ้ำตอนนี้ถือเป็น antipattern และยูทิลิตี้ของมันได้หายไปเนื่องจากเวลาเริ่มต้น JVM เร็วขึ้น
ตัวอย่างอื่นๆ
Java API ให้ singletons ต่อไปนี้แก่เรา:
java.lang.รันไทม์
java.awt.Desktop
คำเตือน
คุณสามารถ subclass คลาส singleton ได้โดยการปกป้องตัวสร้างแทนที่จะเป็นแบบส่วนตัว อย่างไรก็ตาม มีตัวเลือกที่ดีกว่านี้ในทุกสถานการณ์ ในสถานการณ์เหล่านี้ นักพัฒนาสามารถสร้างรีจีสทรีซิงเกิลตันสำหรับคลาสย่อยทั้งหมดได้ เมธอด getInstance สามารถใช้พารามิเตอร์หรือใช้ตัวแปรสภาพแวดล้อมเพื่อส่งคืนออบเจกต์ singleton ที่ต้องการ รีจิสทรีรักษาการแมปชื่อสตริงกับวัตถุซิงเกิล





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)