javascript - วิธีสร้างคลาสที่ไม่สามารถสร้างอินสแตนซ์ภายนอกใน TypeScript ได้?
ในภาษา Java เรามีตัวสร้างแบบส่วนตัว
public class Singleton{
private static volatile Singleton INSTANCE = null;
private Singleton(){ }
public static Singleton getInstance(){
if(INSTANCE == null){
synchronized(Singleton.class){
if(INSTANCE == null){
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
ซึ่งทำให้คลาสไม่สามารถสร้างอินสแตนซ์นอกคลาสได้ มีสิ่งแบบนั้นใน TypeScript ไหม?
คำตอบ #1
ฉันจะเริ่มจากส่วนของจาวา และจะเพิ่มสิ่งหนึ่งเพิ่มเติมจากที่ @DavideLorenzoMARINO เขียน นั่นคือคีย์เวิร์ด volatile:
class MySingleton {
private static volatile MySingleton instance;
private MySingleton() {
// do what ever
}
public static MySingleton getInstance() {
if (MySingleton.instance == null) {
MySingleton.instance = new MySingleton();
}
return MySingleton.instance;
}
}
หากคุณต้องการให้แน่ใจว่าสิ่งนี้ทำงานได้ในสภาพแวดล้อมแบบมัลติเธรด คุณอาจต้องพิจารณาวิธีการที่เรียกว่า "Double Checked Locking" ด้วย:
class MySingleton {
private static volatile MySingleton instance;
private MySingleton() {
// do what ever
}
public static MySingleton getInstance() {
if (MySingleton.instance == null) {
synchronized (MySingleton.class) {
if (MySingleton.instance == null) {
MySingleton.instance = new MySingleton();
}
}
}
return MySingleton.instance;
}
}
ส่วนของ TypeScript ผมคิดว่ารูปแบบนี้ไม่ค่อยเหมาะสมกับ TypeScript เพราะต่างจาก Java ในเวลารันไทม์ไม่มีอะไรป้องกันนักพัฒนาคนอื่นจากการสร้างอินสแตนซ์มากกว่าหนึ่งตัว
ถ้าคุณเชื่อถือผู้พัฒนาที่ทำงานกับโค้ดก็ถือว่าโอเค แต่ถ้าไม่เชื่อ ทำไมไม่ห่ออินสแตนซ์นั้นในโมดูล/เนมสเปซเพื่อซ่อนการทำงานล่ะ?
บางอย่างเช่น:
namespace MySingleton {
class MySingletonInstance {
echo(value: string): string {
console.log(value);
return value;
}
}
export var instance = new MySingletonInstance();
}
แต่เนื่องจากคุณจะมีเพียงตัวอย่างเดียวของคลาสนี้ ดังนั้นฉันคิดว่าในจาวาสคริปต์จะสมเหตุสมผลกว่าที่จะไม่ใช้คลาสเลย มันทำให้โค้ดยืดยาวขึ้น และคุณสามารถทำได้ง่ายๆ ดังนี้:
namespace MySingleton {
export interface MySingletonInstance {
echo(value: string): string;
}
export var instance: MySingletonInstance = {
echo: value => {
console.log(value);
return value;
}
}
}
คำตอบ #2
สิ่งที่ประมาณนั้นน่าจะใช้ได้:
class Singleton {
private static _instance:Singleton = new Singleton();
constructor() {
if (Singleton._instance){
throw new Error("Error: use getInstance()");
}
Singleton._instance = this;
}
public static getInstance():Singleton {
return Singleton._instance;
}
...
}
นอกจากนี้ในภาษา Java ไม่จำเป็นต้องใช้การเริ่มต้นแบบ Lazy เนื่องจาก Singleton จะไม่ถูกสร้างขึ้นหากไม่ได้ใช้งาน วิธีที่ดีกว่า:
public class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public Singleton getInstance(){
return INSTANCE;
}
}
เพื่อตอบความคิดเห็นของ Zhipeng การกำหนดค่าเริ่มต้นแบบคงที่ปลอดภัยสำหรับเธรด ตามที่กำหนดใน JLS ที่ 12.4.2:
การใช้งานของ Java Virtual Machine รับผิดชอบในการจัดการการซิงโครไนซ์และการเริ่มต้นแบบเรียกซ้ำ โดยใช้ขั้นตอนดังต่อไปนี้...
หมายเหตุ: การใช้การใช้งานแบบขี้เกียจมีประโยชน์ก็ต่อเมื่อสามารถใช้วิธีสแตติกบางอย่างโดยไม่ต้องใช้ getInstance() ในกรณีนี้ คลาส Singleton จะถูกสร้างอินสแตนซ์แม้ว่าจะไม่เคยถูกใช้งานก็ตาม
สำหรับคำอธิบายอย่างสมบูรณ์เกี่ยวกับ Singleton ใน Java คุณสามารถดูบทความที่ฉันเขียนสำหรับ Dzone ได้
