![รูปแบบการออกแบบ: Singleton - 1](https://cdn.codegym.cc/images/article/ae7ec2ba-45e7-465d-ad8a-f13139cbdfed/800.jpeg)
singleton ใน Java คืออะไร?
Singleton เป็นหนึ่งในรูปแบบการออกแบบระดับคลาสที่ง่ายที่สุด บางครั้งมีคนพูดว่า "คลาสนี้เป็นซิงเกิลตัน" ซึ่งหมายความว่าคลาสใช้รูปแบบการออกแบบซิงเกิลตัน บางครั้งจำเป็นต้องเขียนคลาสโดยที่เราจำกัดการสร้างอินสแตนซ์ไว้ที่ออบเจกต์เดียว ตัวอย่างเช่น คลาสที่มีหน้าที่บันทึกหรือเชื่อมต่อกับ ฐานข้อมูล รูปแบบการออกแบบ singleton อธิบายว่าเราสามารถบรรลุสิ่งนี้ได้อย่างไร singleton เป็นรูปแบบการออกแบบที่ทำสองสิ่ง:-
รับประกันได้ว่าจะมีเพียงหนึ่งตัวอย่างในชั้นเรียนเท่านั้น
-
ให้จุดเดียวของการเข้าถึงทั่วโลกไปยังอินสแตนซ์นั้น
-
ตัวสร้างส่วนตัว สิ่งนี้จำกัดความสามารถในการสร้างวัตถุของคลาสนอกคลาส
-
เมธอดสแตติกสาธารณะที่ส่งคืนอินสแตนซ์ของคลาส วิธีนี้เรียกว่าgetInstance นี่คือจุดของการเข้าถึงอินสแตนซ์ของคลาสทั่วโลก
ตัวเลือกการใช้งาน
รูปแบบการออกแบบ singleton ถูกนำมาใช้ในรูปแบบต่างๆ แต่ละตัวเลือกมีดีและไม่ดีในแบบของตัวเอง เช่นเคยไม่มีตัวเลือกที่สมบูรณ์แบบที่นี่ แต่เราควรพยายามอย่างใดอย่างหนึ่ง ก่อนอื่น เรามาตัดสินใจกันว่าอะไรคือสิ่งที่ดีและไม่ดี และเมตริกใดที่ส่งผลต่อวิธีที่เราประเมินการใช้งานรูปแบบการออกแบบต่างๆ เริ่มจากสิ่งที่ดีกันเถอะ นี่คือปัจจัยที่ทำให้การใช้งานมีความน่าสนใจและน่าดึงดูดยิ่งขึ้น:-
การเริ่มต้นแบบขี้เกียจ: อินสแตนซ์จะไม่ถูกสร้างจนกว่าจะจำเป็น
-
รหัสที่เรียบง่ายและโปร่งใส: แน่นอนว่าเมตริกนี้เป็นอัตนัย แต่ก็มีความสำคัญ
-
ความปลอดภัยของเธรด: การทำงานที่ถูกต้องในสภาพแวดล้อมแบบมัลติเธรด
-
ประสิทธิภาพสูงในสภาพแวดล้อมแบบมัลติเธรด: การบล็อกเธรดเพียงเล็กน้อยหรือไม่มีเลยเมื่อแบ่งปันทรัพยากร
-
ไม่มีการเริ่มต้นแบบขี้เกียจ: เมื่อคลาสถูกโหลดเมื่อแอปพลิเคชันเริ่มทำงาน ไม่ว่าจะจำเป็นหรือไม่ก็ตาม (ซึ่งขัดแย้งกัน ในโลกไอที การขี้เกียจจะดีกว่า)
-
รหัสที่ซับซ้อนและอ่านยาก เมตริกนี้เป็นอัตนัยเช่นกัน หากดวงตาของคุณเริ่มมีเลือดออก เราจะถือว่าการดำเนินการนั้นไม่ดีที่สุด
-
ขาดความปลอดภัยของเธรด กล่าวอีกนัยหนึ่งคือ "อันตรายจากด้าย" การดำเนินการที่ไม่ถูกต้องในสภาพแวดล้อมแบบมัลติเธรด
-
ประสิทธิภาพต่ำในสภาพแวดล้อมแบบมัลติเธรด: เธรดบล็อกกันตลอดเวลาหรือบ่อยครั้งเมื่อแบ่งปันทรัพยากร
รหัส
ตอนนี้เราพร้อมที่จะพิจารณาตัวเลือกการใช้งานต่างๆ และระบุข้อดีและข้อเสีย:เรียบง่าย
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
การใช้งานที่ง่ายที่สุด ข้อดี:
-
รหัสที่เรียบง่ายและโปร่งใส
-
ความปลอดภัยของเธรด
-
ประสิทธิภาพสูงในสภาพแวดล้อมแบบมัลติเธรด
- ไม่มีการเริ่มต้นขี้เกียจ
การเริ่มต้นขี้เกียจ
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
ข้อดี:
-
การเริ่มต้นขี้เกียจ
-
ไม่ด้ายปลอดภัย
การเข้าถึงแบบซิงโครไนซ์
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
ข้อดี:
-
การเริ่มต้นขี้เกียจ
-
ความปลอดภัยของเธรด
-
ประสิทธิภาพการทำงานแบบมัลติเธรดต่ำ
ตรวจสอบการล็อคสองครั้ง
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
ข้อดี:
-
การเริ่มต้นขี้เกียจ
-
ความปลอดภัยของเธรด
-
ประสิทธิภาพสูงในสภาพแวดล้อมแบบมัลติเธรด
-
ไม่รองรับใน Java เวอร์ชันก่อนหน้าที่ต่ำกว่า 1.5 (การใช้คีย์เวิร์ดระเหยได้รับการแก้ไขตั้งแต่เวอร์ชัน 1.5)
เจ้าของชั้นเรียน
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
ข้อดี:
-
การเริ่มต้นขี้เกียจ
-
ความปลอดภัยของเธรด
-
ประสิทธิภาพสูงในสภาพแวดล้อมแบบมัลติเธรด
-
การดำเนินการที่ถูกต้องต้องการการรับประกันว่า ออบเจกต์ ซิงเกิลตันเริ่มต้นได้โดยไม่มีข้อผิดพลาด มิฉะนั้น การเรียกเมธอด getInstance ครั้งแรกจะส่งผลให้เกิดExceptionInInitializerErrorและการเรียกที่ตามมาทั้งหมดจะทำให้เกิดNoClassDefFoundError
การดำเนินการ | การเริ่มต้นขี้เกียจ | ความปลอดภัยของเธรด | ประสิทธิภาพการทำงานแบบมัลติเธรด | ใช้เมื่อไหร่? |
---|---|---|---|---|
เรียบง่าย | - | + | เร็ว | ไม่เคย. หรือเป็นไปได้เมื่อการเริ่มต้นแบบขี้เกียจนั้นไม่สำคัญ แต่ไม่เคยจะดีกว่า |
การเริ่มต้นขี้เกียจ | + | - | ไม่สามารถใช้ได้ | เสมอเมื่อไม่ต้องการมัลติเธรด |
การเข้าถึงแบบซิงโครไนซ์ | + | + | ช้า | ไม่เคย. หรือเป็นไปได้เมื่อประสิทธิภาพของมัลติเธรดไม่สำคัญ แต่ไม่เคยจะดีกว่า |
ตรวจสอบการล็อคสองครั้ง | + | + | เร็ว | ในบางกรณีที่เกิดขึ้นไม่บ่อยเมื่อคุณต้องการจัดการกับข้อยกเว้นเมื่อสร้างซิงเกิลตัน (เมื่อไม่สามารถใช้ซิงเกิลตันตัวยึดคลาสได้) |
เจ้าของชั้นเรียน | + | + | เร็ว | เมื่อใดก็ตามที่จำเป็นต้องใช้มัลติเธรดและมีการรับประกันว่าอ็อบเจกต์ singleton จะถูกสร้างขึ้นโดยไม่มีปัญหา |
ข้อดีและข้อเสียของรูปแบบซิงเกิลตัน
โดยทั่วไป singleton ทำในสิ่งที่คาดหวัง:-
รับประกันได้ว่าจะมีเพียงหนึ่งตัวอย่างในชั้นเรียนเท่านั้น
-
ให้จุดเดียวของการเข้าถึงทั่วโลกไปยังอินสแตนซ์นั้น
-
ซิงเกิลตันละเมิดหลักการความรับผิดชอบเดียว: นอกเหนือจากหน้าที่โดยตรงแล้ว คลาสซิงเกิลตันยังควบคุมจำนวนอินสแตนซ์ด้วย
-
การพึ่งพาของชนชั้นสามัญในซิงเกิลไม่สามารถมองเห็นได้ในสัญญาสาธารณะของชั้นเรียน
-
ตัวแปรส่วนกลางไม่ดี ในที่สุด singleton กลายเป็นตัวแปรระดับโลกที่หนักหน่วง
-
การมีซิงเกิลตันช่วยลดความสามารถในการทดสอบของแอปพลิเคชันโดยรวมและคลาสที่ใช้ซิงเกิลตันโดยเฉพาะ
GO TO FULL VERSION