มีทางเลือกอื่นสำหรับ GOF Singleton Pattern หรือไม่?


91

มาเผชิญหน้ากันเถอะ รูปแบบ Singleton เป็นหัวข้อที่ถกเถียงกันอย่างมากกับโปรแกรมเมอร์พยุหะทั้งสองด้านของรั้ว มีผู้ที่รู้สึกว่า Singleton ไม่ได้เป็นเพียงตัวแปรระดับโลกที่น่ายกย่องอีกต่อไปและคนอื่น ๆ ที่สาบานด้วยแบบแผนและใช้มันอย่างไม่หยุดหย่อน อย่างไรก็ตามฉันไม่ต้องการให้การโต้เถียง Singletonอยู่ในหัวใจของคำถามของฉัน ทุกคนสามารถมีชักชวนของสงครามและการต่อสู้มันออกมาและดูว่าใครชนะสำหรับการดูแลผมทั้งหมด สิ่งที่ฉันพยายามจะพูดคือฉันไม่เชื่อว่าจะมีคำตอบที่ถูกต้องเพียงคำเดียวและฉันไม่ได้มีเจตนาที่จะพยายามก่อกวนการทะเลาะวิวาทของพรรคพวก ฉันสนใจเพียงทางเลือกเดียวเมื่อฉันถามคำถาม:

มีทางเลือกอื่นสำหรับ GOF Singleton Pattern หรือไม่?

ตัวอย่างเช่นหลายครั้งที่ฉันเคยใช้รูปแบบซิงเกิลตันในอดีตฉันสนใจแค่การรักษาสถานะ / ค่าของตัวแปรหนึ่งหรือหลายตัวแปร อย่างไรก็ตามสถานะ / ค่าของตัวแปรสามารถเก็บรักษาไว้ระหว่างแต่ละอินสแตนซ์ของคลาสโดยใช้ตัวแปรคงที่แทนที่จะใช้รูปแบบซิงเกิลตัน

คุณมีแนวคิดอะไรอีกบ้าง?

แก้ไข: ฉันไม่อยากให้นี่เป็นอีกโพสต์เกี่ยวกับ "วิธีใช้ซิงเกิลตันอย่างถูกต้อง" อีกครั้งฉันกำลังมองหาวิธีหลีกเลี่ยง เพื่อความสนุกสนานโอเค? ฉันเดาว่าฉันกำลังถามคำถามเชิงวิชาการอย่างหมดจดในเสียงตัวอย่างภาพยนตร์ที่ดีที่สุดของคุณ "ในจักรวาลคู่ขนานที่ไม่มีซิงเกิลตันเราจะทำอย่างไร"


อะไร? มันไม่ดีหรือไม่ดี แต่ฉันจะแทนที่ได้อย่างไร สำหรับทุกคนที่บอกว่าดี - อย่าเข้าร่วม พวกคุณทุกคนที่บอกว่ามันไม่ดีพิสูจน์ด้วยการแสดงให้ฉันเห็นว่าฉันจะอยู่ได้อย่างไรถ้าไม่มีมัน ฟังดูโต้แย้งสำหรับฉัน
ล็อ

@CodingWithoutComents: ได้อ่านโพสต์ทั้งหมด นั่นคือสิ่งที่ฉันรู้สึกว่า "อย่าตอบกลับถ้าคุณคิดว่า Singletons โอเค"
ล็อ

2
ถ้าเป็นเช่นนั้นฉันขอโทษด้วย ฉันคิดว่าฉันทำตามขั้นตอนสำคัญเพื่อหลีกเลี่ยงการโพลาไรซ์ ฉันคิดว่าฉันถามคำถามในลักษณะที่ทั้งคนรักและผู้เกลียดชัง Singletons ทั้งคู่สามารถหลีกหนีจากสิ่งนั้นได้ในฐานะโปรแกรมเมอร์เราทุกคนมีทางเลือกว่าพวกเขาไม่ได้มีเพียงวิธีเดียวที่ถูกต้อง
CodingWithout คอมเมนต์

ถ้าฉันใช้ Singletons ฉันจะไม่มีส่วนช่วยในการแก้ไขปัญหาเหล่านี้ เสียงโพลาไรซ์สำหรับฉัน
ล็อ

9
ฉันใช้ Singletons ทุกวัน แต่นั่นทำให้ฉันหยุดคิดว่าอาจมีวิธีที่ดีกว่าในการทำสิ่งต่างๆหรือไม่? รูปแบบการออกแบบมีมาเพียง 14 ปี ฉันถือว่าพวกเขาเป็นความจริงในพระคัมภีร์หรือไม่? เราเลิกพยายามคิดนอกกรอบไหม? เราไม่พยายามที่จะพัฒนาวินัยของ CS?
CodingWithoutComments

คำตอบ:


77

Alex Miller ใน " Patterns I Hate " มีคำพูดต่อไปนี้:

"เมื่อซิงเกิลตันดูเหมือนคำตอบฉันมักจะฉลาดกว่าที่จะ:

  1. สร้างอินเทอร์เฟซและการใช้งาน Singleton เริ่มต้นของคุณ
  2. สร้างอินสแตนซ์เดียวของการใช้งานเริ่มต้นของคุณที่ "ด้านบน" ของระบบของคุณ สิ่งนี้อาจอยู่ในการกำหนดค่า Spring หรือในโค้ดหรือกำหนดไว้หลายวิธีขึ้นอยู่กับระบบของคุณ
  3. ส่งอินสแตนซ์เดียวไปยังแต่ละองค์ประกอบที่ต้องการ (การฉีดขึ้นต่อกัน)

2
ฉันรู้ว่านี่ใกล้จะ 5 ขวบแล้ว แต่คุณช่วยขยายความได้ไหม ฉันคิดว่าฉันได้รับการสอนว่าวิธีสร้างซิงเกิลตันที่ถูกต้องคือการใช้อินเทอร์เฟซ ฉันจะสนใจว่าสิ่งที่ฉันทำอยู่นั้น 'ตกลง' หรือไม่และไม่ได้แย่อย่างที่ฉันเคยบอกไป
Pureferret

97

เพื่อให้เข้าใจวิธีการแก้ปัญหา Singletons ที่เหมาะสมคุณต้องเข้าใจว่าอะไรผิดปกติกับ Singletons (และสถานะทั่วโลกโดยทั่วไป):

Singletons ซ่อนการอ้างอิง

สิ่งนั้นสำคัญไฉน?

เนื่องจากหากคุณซ่อนการอ้างอิงคุณมักจะสูญเสียการติดตามจำนวนการมีเพศสัมพันธ์

คุณอาจเถียงว่า

void purchaseLaptop(String creditCardNumber, int price){
  CreditCardProcessor.getInstance().debit(creditCardNumber, amount);
  Cart.getInstance().addLaptop();
}

ง่ายกว่า

void purchaseLaptop(CreditCardProcessor creditCardProcessor, Cart cart, 
                    String creditCardNumber, int price){
  creditCardProcessor.debit(creditCardNumber, amount);
  cart.addLaptop();
}

แต่อย่างน้อย API ที่สองก็ทำให้ชัดเจนว่าผู้ทำงานร่วมกันของเมธอดคืออะไร

ดังนั้นวิธีแก้ปัญหา Singletons ไม่ใช่การใช้ตัวแปรแบบคงที่หรือตัวระบุตำแหน่งบริการ แต่เป็นการเปลี่ยนคลาส Singleton เป็นอินสแตนซ์ซึ่งเป็นอินสแตนซ์ในขอบเขตที่เหมาะสมและฉีดเข้าไปในส่วนประกอบและวิธีการที่ต้องการ คุณอาจใช้ IoC-framework เพื่อจัดการสิ่งนี้หรือคุณอาจทำด้วยตนเอง แต่สิ่งสำคัญคือการกำจัดสภาวะโลกของคุณและทำให้การอ้างอิงและการทำงานร่วมกันมีความชัดเจน


+1 สำหรับการพูดคุยถึงต้นตอของปัญหาไม่ใช่แค่วิธีแก้ปัญหา
ฟิล

9
ในแอปพลิเคชันแบบหลายชั้นเต็มรูปแบบวิธีที่สองมักจะสร้างโค้ดที่ไม่จำเป็นจำนวนมาก ด้วยการทำให้รหัสระดับกลางเป็นมลพิษด้วยตรรกะในการส่งผ่านไปยังระดับที่ต่ำกว่าวัตถุที่ไม่จำเป็นในระดับนั้นเราไม่ได้สร้างการอ้างอิงที่ไม่จำเป็นหรือ? การพูดว่าเทียร์ 4 ในสแต็กการนำทางจะเริ่มการทำงานเบื้องหลังเช่นการอัปโหลดไฟล์ ตอนนี้สมมติว่าคุณต้องการแจ้งเตือนผู้ใช้เมื่อดำเนินการเสร็จสิ้น แต่ในตอนนี้ผู้ใช้อาจอยู่ในส่วนที่แตกต่างไปจากเดิมโดยสิ้นเชิงของแอปพลิเคชันซึ่งแชร์เฉพาะระดับ 1 เหมือนกันกับมุมมองเริ่มต้น รหัสที่ไม่จำเป็นมากมาย ...
Hari Karam Singh

1
@RasmusFaber รูปแบบ Singleton ไม่ซ่อนการอ้างอิง คุณกำลังร้องเรียนเกี่ยวกับการซ่อนการอ้างอิงเป็นข้อกังวลที่แยกต่างหากจากรูปแบบ จริงอยู่ที่รูปแบบทำให้เกิดความผิดพลาดนี้ได้ง่าย แต่เป็นไปได้มากที่จะดำเนินการรูปแบบ IoC และ Singleton ด้วยกันอย่างกลมกลืน ตัวอย่างเช่นฉันสามารถสร้าง lib ของบุคคลที่สามที่ต้องการการจัดการวงจรชีวิตแบบพิเศษของอินสแตนซ์ได้และใครก็ตามที่ใช้ lib ของฉันควร "ส่ง" อินสแตนซ์ของซิงเกิลตันไปยังคลาสของพวกเขาโดยใช้ Dependency Injection แบบคลาสสิกแทนที่จะเป็น "sky hook" ซิงเกิลตันของฉัน จากทุกจุด
Martin Bliss

@HariKaramSingh คุณสามารถใช้รูปแบบสมัครสมาชิก / เผยแพร่หรือบัสเหตุการณ์ทั้งระบบ (ซึ่งต้องแชร์กับทุกฝ่ายที่เกี่ยวข้องไม่ใช่ซิงเกิลตัน) เพื่อแก้ไขปัญหานี้
Victor Sorokin

4
นอกจากนี้รูปแบบ pub / sub หรือ observer ก็อาจเป็นได้เช่นเดียวกับ "การสูญเสียการติดตามการมีเพศสัมพันธ์" ที่ไม่ดีเช่นเดียวกับใครก็ตามที่ต้องแก้ไขข้อบกพร่องผ่านเฟรมเวิร์กที่ต้องอาศัยโครงสร้างเหล่านี้อย่างมาก อย่างน้อยด้วย singleton ชื่อวิธีการที่เรียกใช้จะอยู่ที่เดียวกับโค้ดที่เรียกใช้ :) โดยส่วนตัวแล้วฉันคิดว่ากลยุทธ์เหล่านี้ทั้งหมดมีที่มาและไม่มีใครสามารถนำไปใช้แบบสุ่มสี่สุ่มห้าได้ โปรแกรมเขียนโค้ดที่เลอะเทอะจะทำให้สปาเก็ตตี้ไม่อยู่ในรูปแบบใด ๆ และผู้เขียนโค้ดที่รับผิดชอบไม่จำเป็นต้องสร้างภาระให้ตัวเองมากเกินไปด้วยข้อ จำกัด ทางอุดมการณ์ในการสร้างโค้ดที่สวยงาม
Hari Karam Singh

14

ทางออกที่ดีที่สุดที่ฉันพบคือการใช้รูปแบบโรงงานเพื่อสร้างอินสแตนซ์ของชั้นเรียนของคุณ เมื่อใช้รูปแบบนี้คุณสามารถมั่นใจได้ว่ามีเพียงอินสแตนซ์เดียวของคลาสที่แบ่งใช้ระหว่างอ็อบเจ็กต์ที่ใช้

ฉันแม้ว่ามันจะยุ่งยากในการจัดการ แต่หลังจากอ่านบล็อกโพสต์นี้"Singletons ทั้งหมดหายไปไหน" ดูเหมือนเป็นธรรมชาติ และนอกจากนี้ยังช่วยได้มากในการแยกการทดสอบหน่วยของคุณ

สรุปต้องทำอย่างไร? เมื่อใดก็ตามที่วัตถุขึ้นอยู่กับวัตถุอื่นมันจะได้รับอินสแตนซ์ของมันผ่านตัวสร้างของมันเท่านั้น (ไม่มีคีย์เวิร์ดใหม่ในคลาสของคุณ)

class NeedyClass {

    private ExSingletonClass exSingleton;

    public NeedyClass(ExSingletonClass exSingleton){
        this.exSingleton = exSingleton;
    }

    // Here goes some code that uses the exSingleton object
}

จากนั้นโรงงาน

class FactoryOfNeedy {

    private ExSingletonClass exSingleton;

    public FactoryOfNeedy() {
        this.exSingleton = new ExSingletonClass();
    }

    public NeedyClass buildNeedy() {
        return new NeedyClass(this.exSingleton);
    }
}

เนื่องจากคุณจะสร้างอินสแตนซ์โรงงานของคุณเพียงครั้งเดียวจะมีการสร้างอินสแตนซ์ exSingleton เพียงครั้งเดียว ทุกครั้งที่คุณเรียก buildNeedy อินสแตนซ์ใหม่ของ NeedyClass จะมาพร้อมกับ exSingleton

ฉันหวังว่านี่จะช่วยได้. กรุณาชี้ข้อผิดพลาดประการใด


5
เพื่อให้แน่ใจว่าโรงงานของคุณได้รับการสร้างอินสแตนซ์เพียงครั้งเดียวเท่านั้นที่คุณต้องการ construtor ส่วนตัวและกำหนดเมธอด buildNeedy เป็นวิธีคงที่
Julien Grenier

16
Julien พูดถูกการแก้ไขนี้มีข้อบกพร่องพื้นฐานนั่นคือคุณบอกเป็นนัยว่าคุณสามารถสร้างโรงงานได้เพียงแห่งเดียว หากคุณใช้มาตรการป้องกันที่จำเป็นเพื่อให้แน่ใจว่ามีเพียงโรงงานเดียวเท่านั้นที่สร้างอินสแตนซ์ได้ (เช่นเดียวกับสิ่งที่ Julien พูด) คุณจะจบลงด้วย ... ซิงเกิลตัน! ในความเป็นจริงวิธีนี้เพียงแค่เพิ่มชั้นนามธรรมที่ไม่จำเป็นที่ด้านบนของซิงเกิลตัน
Bob Somers

มีอีกวิธีหนึ่งในการมีเพียงอินสแตนซ์เดียว คุณสามารถสร้างโรงงานของคุณได้เพียงครั้งเดียว ไม่จำเป็นต้องบังคับใช้สิ่งนี้โดยคอมไพเลอร์ นอกจากนี้ยังช่วยในเรื่อง unittests ที่คุณต้องการอินสแตนซ์อื่น
frast

นี่เป็นวิธีแก้ปัญหาที่ดีที่สุดที่ฉันเคยเห็นมาก่อนสำหรับปัญหาที่แก้ไขอย่างผิดพลาดด้วย singletons - เพิ่มการอ้างอิงโดยไม่ทำให้การเรียกใช้เมธอดทุกครั้งเกะกะ (ดังนั้นจึงออกแบบอินเทอร์เฟซใหม่และปรับโครงสร้างการอ้างอิงใหม่) การปรับเปลี่ยนเล็กน้อยเหมาะอย่างยิ่งสำหรับสถานการณ์ของฉันที่ไม่สำคัญว่าจะมี "ซิงเกิลตัน" เพียงอินสแตนซ์เดียว แต่สิ่งสำคัญคือทุกคนจะแชร์อินสแตนซ์เดียวกันตามค่าเริ่มต้น (การแก้ไขคือ: แทนที่จะใช้โรงงานให้ใช้แบบคงที่ วิธีการตั้งค่าอินสแตนซ์ทั่วไปจากภายนอกและใช้อินสแตนซ์นั้นในระหว่างการก่อสร้าง)
meustrus

ดังนั้นโดยพื้นฐานแล้วข้อดีของวิธีนี้คือคุณต้องสับเปลี่ยนรอบ ๆอินสแตนซ์อ็อบเจ็กต์เดียว (โรงงาน) แทนที่จะเป็นอ็อบเจ็กต์ทั้งหมด (ซึ่งคุณเลือกที่จะไม่ใช้ Singletons)?
Hari Karam Singh

9

Spring หรือ IoC-Container อื่น ๆ ทำงานได้ดีพอสมควร เนื่องจากคลาสถูกสร้างและจัดการภายนอกแอปคอนเทนเนอร์จึงสามารถสร้างคลาสเดี่ยวแบบง่ายและฉีดได้ตามต้องการ


มีลิงค์เกี่ยวกับหัวข้อข้างต้นหรือไม่?
CodingWithoutComments

กรอบงานเหล่านี้ดูเหมือนเฉพาะสำหรับ java - มีตัวเลือกเฉพาะภาษาอื่น ๆ หรือไม่? หรือไม่เชื่อเรื่องพระเจ้าภาษา?
CodingWithoutComments

สำหรับ. NET: Castle Windsor castleproject.org/container/index.html Microsoft Unity msdn.microsoft.com/en-us/library/cc468366.aspx Unity เป็นเฟรมเวิร์กการฉีดแบบพึ่งพา แต่อาจใช้ได้กับหัวข้อนี้
Erik van Brakel

1
ทำไมถึงมีคนโหวตไม่มากเกินไป IOC เป็นทางออกที่สมบูรณ์แบบในการหลีกเลี่ยง Singleton
Sandeep Jindal

@CodingWithoutComments ฉันรู้ว่า PHP มี Symfony Service Container พวกทับทิมมีวิธีอื่นในการฉีดพึ่งพา คุณมีภาษาเฉพาะที่คุณสนใจหรือไม่?
Bevelopper

9

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

ฉันไม่ได้หลีกเลี่ยงรูปแบบซิงเกิลตัน ไม่ว่าจะเหมาะสมและฉันใช้หรือไม่เหมาะสมและฉันไม่ได้ใช้ ฉันเชื่อว่ามันง่ายอย่างนั้น

ความเหมาะสม (หรือขาด) ของ Singleton ขึ้นอยู่กับสถานการณ์ เป็นการตัดสินใจออกแบบที่ต้องทำและต้องเข้าใจผลที่ตามมาของการตัดสินใจนั้น (และจัดทำเป็นเอกสาร)


ฉันจะพูดในสิ่งเดียวกัน แต่มันไม่ค่อยตอบคำถามของเขา :)
Swati

2
โปรดพูดถึงในคำตอบของคุณว่าเหมาะสมหรือไม่เหมาะสม กรุณาสวย
CodingWithoutComments

มันตอบคำถาม ฉันไม่มีเทคนิคในการหลีกเลี่ยงการใช้รูปแบบ Singleton เพราะฉันไม่หลีกเลี่ยงวิธีหลีกเลี่ยงและฉันไม่คิดว่านักพัฒนาคนใดควร
Thomas Owens

ฉันไม่คิดว่าคุณสามารถสรุปได้ว่ามันเหมาะสมหรือไม่เหมาะสม ทั้งหมดเป็นโครงการเฉพาะและขึ้นอยู่กับการออกแบบระบบที่เป็นปัญหาอย่างมาก ฉันไม่ใช้ "กฎนิ้วหัวแม่มือ" ในการตัดสินใจเช่นนี้
Thomas Owens

อืม. ฉันไม่เข้าใจว่าทำไมถึงได้รับการโหวตลง ฉันตอบคำถาม - คุณมีเทคนิคอะไรในการหลีกเลี่ยงการใช้รูปแบบซิงเกิลตัน - โดยบอกว่าฉันไม่มีเทคนิคเพราะฉันไม่ออกนอกลู่นอกทางเพื่อหลีกเลี่ยงรูปแบบ ผู้ลงคะแนนสามารถอธิบายเหตุผลของตนอย่างละเอียดได้หรือไม่?
Thomas Owens

5

Monostate (อธิบายไว้ใน Agile Software Development ของ Robert C.Martin) เป็นอีกทางเลือกหนึ่งของ Singleton ในรูปแบบนี้ข้อมูลของคลาสทั้งหมดเป็นแบบคงที่ แต่ getters / setters ไม่คงที่

ตัวอย่างเช่น:

public class MonoStateExample
{
    private static int x;

    public int getX()
    {
        return x;
    }

    public void setX(int xVal)
    {
        x = xVal;
    }
}

public class MonoDriver
{
    public static void main(String args[])
    {
        MonoStateExample m1 = new MonoStateExample();
        m1.setX(10);

        MonoStateExample m2 = new MonoStateExample();
        if(m1.getX() == m2.getX())
        {
            //singleton behavior
        }
    }
}

Monostate มีพฤติกรรมคล้ายกับซิงเกิลตัน แต่ทำในลักษณะที่โปรแกรมเมอร์ไม่จำเป็นต้องตระหนักถึงความจริงที่ว่ามีการใช้ซิงเกิลตัน


สิ่งนี้สมควรได้รับการโหวตมากกว่านี้ ฉันมาที่นี่จาก Google เพื่อค้นหาการทบทวน MonoState!
mahemoff

@ มาร์คดูเหมือนว่าการออกแบบนี้ยากมากที่จะล็อคในแง่ของความปลอดภัยของด้าย ฉันสร้างการล็อกอินสแตนซ์สำหรับตัวแปรแบบคงที่ใน MonoStateExample หรือไม่หรือฉันสร้างการล็อกหนึ่งรายการที่คุณสมบัติทั้งหมดใช้ประโยชน์ได้ ทั้งสองมีการแบ่งส่วนที่ร้ายแรงซึ่งแก้ไขได้ง่ายในรูปแบบซิงเกิลตัน
Martin Bliss

ตัวอย่างนี้เป็นทางเลือกหนึ่งของรูปแบบ Singleton แต่ไม่สามารถแก้ปัญหาของรูปแบบ Singleton ได้
Sandeep Jindal

4

เดี่ยวรูปแบบที่มีอยู่เพราะมีสถานการณ์เมื่อวัตถุเดียวเป็นสิ่งจำเป็นเพื่อให้ชุดของบริการ

แม้ว่าจะเป็นกรณีนี้ฉันก็ยังคงพิจารณาแนวทางในการสร้าง singletons โดยใช้global static field / propertyแทนอินสแตนซ์นั้นไม่เหมาะสม ไม่เหมาะสมเนื่องจากสร้างการอ้างอิงในโค้ดระหว่างฟิลด์สแตติกและอ็อบเจ็กต์ไม่ใช่บริการที่อ็อบเจ็กต์มีให้

ดังนั้นแทนที่จะใช้รูปแบบซิงเกิลตันแบบคลาสสิกฉันขอแนะนำให้ใช้รูปแบบบริการ 'like' กับคอนเทนเนอร์ที่ให้บริการซึ่งแทนที่จะใช้ singleton ของคุณผ่านฟิลด์แบบคงที่คุณจะได้รับการอ้างอิงผ่านวิธี aa เพื่อขอประเภทของบริการที่ต้องการ

*pseudocode* currentContainer.GetServiceByObjectType(singletonType)
//Under the covers the object might be a singleton, but this is hidden to the consumer.

แทนที่จะเป็นโกลบอลเดียว

*pseudocode* singletonType.Instance

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

นอกจากนี้โปรดดูInversion of Controlแนวคิดก็คือการเปิดเผย singletons โดยตรงกับผู้บริโภคคุณจะสร้างการพึ่งพาระหว่างผู้บริโภคและอินสแตนซ์วัตถุไม่ใช่บริการอ็อบเจ็กต์ที่ออบเจ็กต์จัดหาให้

ความคิดเห็นของฉันคือการซ่อนการใช้รูปแบบซิงเกิลตันทุกครั้งที่ทำได้เพราะไม่สามารถหลีกเลี่ยงได้หรือเป็นที่ต้องการเสมอไป


ฉันไม่ค่อยทำตามตัวอย่างของคอนเทนเนอร์ที่ให้บริการ คุณมีแหล่งข้อมูลออนไลน์ที่สามารถเชื่อมโยงได้หรือไม่?
CodingWithoutComments

ลองดูที่ "ปราสาทโครงการ - วินด์เซอร์คอนเทนเนอร์" castleproject.org/container/index.html น่าเสียดายที่หาสิ่งพิมพ์เชิงนามธรรมเกี่ยวกับหัวข้อนี้ได้ยากมาก
Pop Catalin

2

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

(แม้ว่าฉันจะเถียงว่านี่เป็นวิธีที่ผิดในการใช้ Singleton ตั้งแต่แรก)


1

หากปัญหาของคุณคือคุณต้องการรักษาสถานะคุณต้องการคลาส MumbleManager ก่อนที่คุณจะเริ่มทำงานกับระบบลูกค้าของคุณจะสร้าง MumbleManager โดยที่ Mumble เป็นชื่อของระบบ สถานะจะถูกเก็บไว้ผ่านทางนั้น โอกาสที่ MumbleManager ของคุณจะมีกระเป๋าทรัพย์สินที่ถือสถานะของคุณ

สไตล์ประเภทนี้ให้ความรู้สึกเหมือน C และไม่เหมือนวัตถุ - คุณจะพบว่าออบเจ็กต์ที่กำหนดระบบของคุณทั้งหมดจะมีการอ้างอิงถึง MumbleManager เดียวกัน


โดยไม่ต้องสนับสนุนหรือต่อต้าน Singleton ฉันต้องบอกว่าการแก้ปัญหานี้เป็นการต่อต้านรูปแบบ MumbleManager กลายเป็น "คลาสพระเจ้า" ที่มีความรู้ที่แตกต่างกันทุกประเภทละเมิดความรับผิดชอบเดียว มันอาจเป็น Singleton สำหรับทุกแอปพลิเคชันที่ใส่ใจ
Martin Bliss

0

ใช้วัตถุธรรมดาและวัตถุโรงงาน โรงงานมีหน้าที่ในการตรวจสอบอินสแตนซ์และรายละเอียดวัตถุธรรมดาเฉพาะกับข้อมูลการกำหนดค่า (มีตัวอย่าง) และลักษณะการทำงาน


1
โรงงานมักจะเป็นซิงเกิลตันไม่ใช่หรือ? นั่นเป็นวิธีที่ฉันมักจะเห็นรูปแบบโรงงานใช้งาน
Thomas Owens

0

จริงๆแล้วถ้าคุณออกแบบตั้งแต่เริ่มต้นเพื่อหลีกเลี่ยง Singeltons คุณอาจไม่ต้องหลีกเลี่ยงการไม่ใช้ Singletons โดยใช้ตัวแปรแบบคงที่ เมื่อใช้ตัวแปรแบบคงที่คุณกำลังสร้าง Singleton ไม่มากก็น้อยความแตกต่างเพียงอย่างเดียวคือคุณกำลังสร้างอินสแตนซ์ออบเจ็กต์ที่แตกต่างกันอย่างไรก็ตามภายในทั้งหมดจะทำงานราวกับว่าพวกมันกำลังใช้ Singleton

คุณอาจให้ตัวอย่างโดยละเอียดได้ไหมว่าคุณใช้ Singleton ที่ไหนหรือที่ที่ Singleton ใช้อยู่ในปัจจุบันและคุณกำลังพยายามหลีกเลี่ยงการใช้งาน สิ่งนี้สามารถช่วยให้ผู้คนค้นพบวิธีแก้ปัญหาที่แปลกใหม่มากขึ้นว่าสถานการณ์จะจัดการได้อย่างไรโดยไม่มี Singleton เลย

BTW โดยส่วนตัวแล้วฉันไม่มีปัญหากับ Singletons และฉันไม่เข้าใจปัญหาที่คนอื่นมีเกี่ยวกับ Singletons ฉันไม่เห็นอะไรที่ไม่ดีเกี่ยวกับพวกเขา นั่นคือถ้าคุณไม่ได้เหยียดหยามพวกเขา ทุกเทคนิคที่เป็นประโยชน์สามารถนำไปใช้ในทางที่ผิดและหากถูกทำร้ายก็จะนำไปสู่ผลลัพธ์เชิงลบ อีกเทคนิคหนึ่งที่มักใช้ผิดคือการถ่ายทอดทางพันธุกรรม ยังคงไม่มีใครบอกว่ามรดกเป็นสิ่งที่ไม่ดีเพียงเพราะบางคนละเมิดอย่างร้ายแรง


0

โดยส่วนตัวแล้วสำหรับฉันวิธีที่สมเหตุสมผลกว่ามากในการใช้สิ่งที่มีพฤติกรรมเหมือนซิงเกิลตันคือการใช้คลาสคงที่อย่างสมบูรณ์ (สมาชิกแบบคงที่, วิธีการคงที่, คุณสมบัติคงที่) ส่วนใหญ่แล้วฉันใช้วิธีนี้ (ฉันไม่สามารถคิดถึงความแตกต่างของพฤติกรรมใด ๆ จากมุมมองของผู้ใช้)


0

ฉันคิดว่าสถานที่ที่ดีที่สุดสำหรับตำรวจซิงเกิลตันคือระดับการออกแบบชั้นเรียน ในขั้นตอนนี้คุณควรจะสามารถแมปการโต้ตอบระหว่างคลาสและดูว่ามีบางอย่างที่แน่นอนหรือไม่ว่าจำเป็นต้องมีเพียง 1 อินสแตนซ์ของคลาสนี้ตลอดอายุการใช้งาน

หากเป็นเช่นนั้นแสดงว่าคุณมีซิงเกิลตัน หากคุณกำลังโยนเสื้อกล้ามเพื่อความสะดวกในระหว่างการเขียนโค้ดคุณควรกลับมาทบทวนการออกแบบของคุณและหยุดการเขียนโค้ดที่กล่าวว่า singletons :)

ใช่แล้ว "ตำรวจ" คือคำที่ฉันหมายถึงที่นี่แทนที่จะเป็นคำว่า "หลีกเลี่ยง" Singleton ไม่ใช่สิ่งที่จะหลีกเลี่ยงได้ (เช่นเดียวกับตัวแปร goto และ global ไม่ใช่สิ่งที่ควรหลีกเลี่ยง) แต่คุณควรตรวจสอบการใช้งานและตรวจสอบให้แน่ใจว่าเป็นวิธีที่ดีที่สุดในการทำให้สิ่งที่คุณต้องการทำได้อย่างมีประสิทธิภาพ


1
ฉันเข้าใจโดยสิ้นเชิงว่าคุณกำลังพูดว่า workmad และฉันเห็นด้วยอย่างยิ่ง อย่างไรก็ตามคำตอบของคุณยังไม่ตอบคำถามของฉันโดยเฉพาะ ฉันไม่อยากให้คำถามนี้เป็นอีกคำถามที่ว่า "เมื่อใดจึงเหมาะสมที่จะใช้ซิงเกิลตัน" ฉันสนใจแค่ทางเลือกอื่นที่ใช้งานได้กับซิงเกิลตัน
CodingWithoutComments

0

ฉันใช้ซิงเกิลตันเป็นส่วนใหญ่เป็น "คอนเทนเนอร์วิธีการ" โดยไม่มีสถานะเลย หากฉันต้องการแบ่งปันวิธีการเหล่านี้กับหลาย ๆ คลาสและต้องการหลีกเลี่ยงภาระในการสร้างอินสแตนซ์และการเริ่มต้นฉันจะสร้างบริบท / เซสชันและเริ่มต้นคลาสทั้งหมดที่นั่น ทุกอย่างที่อ้างถึงเซสชั่นยังสามารถเข้าถึง "singleton" ได้ด้วยเช่นกัน


0

เนื่องจากไม่ได้ตั้งโปรแกรมในสภาพแวดล้อมเชิงวัตถุอย่างเข้มข้น (เช่น Java) ฉันไม่เข้าใจความซับซ้อนของการสนทนาอย่างสมบูรณ์ แต่ฉันได้ใช้ Singleton ใน PHP 4 ฉันทำเพื่อสร้างตัวจัดการฐานข้อมูล 'กล่องดำ' ที่เริ่มต้นโดยอัตโนมัติและไม่ต้องส่งผ่านการเรียกใช้ฟังก์ชันขึ้นและลงในกรอบที่ไม่สมบูรณ์และค่อนข้างเสีย

หลังจากอ่านลิงก์ของรูปแบบซิงเกิลตันฉันไม่แน่ใจว่าจะใช้มันในลักษณะเดียวกันอีกครั้ง สิ่งที่ต้องการจริงๆคือวัตถุหลายชิ้นที่มีพื้นที่เก็บข้อมูลร่วมกัน (เช่นตัวจัดการฐานข้อมูลจริง) และนี่คือสิ่งที่ฉันโทรเข้ามา

เช่นเดียวกับรูปแบบและอัลกอริทึมส่วนใหญ่การใช้ซิงเกิลตัน 'เพียงเพราะมันเจ๋ง' คือสิ่งที่ไม่ถูกต้องที่ต้องทำ ฉันต้องการการเรียกแบบ 'กล่องดำ' ที่ดูเหมือนซิงเกิลตันมาก และ IMO เป็นวิธีจัดการกับคำถาม: ระวังรูปแบบ แต่ดูขอบเขตที่กว้างขึ้นและระดับที่อินสแตนซ์ต้องไม่ซ้ำกัน


-1

คุณหมายถึงอะไรฉันมีเทคนิคอย่างไรในการหลีกเลี่ยง

เพื่อ "หลีกเลี่ยง" นั่นหมายความว่ามีหลายสถานการณ์ที่ฉันเจอซึ่งรูปแบบซิงเกิลตันนั้นเข้ากันได้ดีโดยธรรมชาติและด้วยเหตุนี้ฉันจึงต้องใช้มาตรการบางอย่างเพื่อกลบเกลื่อนสถานการณ์เหล่านี้

แต่ไม่มี. ฉันไม่จำเป็นต้องหลีกเลี่ยงรูปแบบซิงเกิลตัน มันไม่ได้เกิดขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.