CodeGym /จาวาบล็อก /สุ่ม /รูปแบบและ Singleton ใน Java
John Squirrels
ระดับ
San Francisco

รูปแบบและ Singleton ใน Java

เผยแพร่ในกลุ่ม
บทความนี้มุ่งเป้าไปที่ใครก็ตามที่พบกับแนวคิดของรูปแบบการออกแบบเป็นครั้งแรก เคยได้ยินคำว่าsingletonหรือนำรูปแบบ singleton มาใช้แต่ไม่เข้าใจว่าเกิดอะไรขึ้น ยินดีต้อนรับ! นักเรียน CodeGym พบกับรูปแบบการออกแบบเป็นครั้งแรกในระดับ 15 เมื่อกัปตันขอให้พวกเขา "เสริม" ความเข้าใจโดยไม่คาดคิดโดยการนำรูปแบบ Java Singleton ไปใช้โดยไม่ได้ตั้งใจ นักเรียนที่ได้ยินเกี่ยวกับ รูปแบบ ซิงเกิลตันเป็นครั้งแรกจะมีคำถามมากมายในทันทีว่ารูปแบบการออกแบบคืออะไรในโลกนี้ ทำไมเราต้องการมัน? ซิงเกิลตันคืออะไร? และสุดท้าย การนำไปใช้อย่างขี้เกียจคืออะไร? มาตอบคำถามเหล่านี้ตามลำดับ

รูปแบบการออกแบบในโลกคืออะไร?

ฉันเชื่อว่าประวัติเล็กน้อยเพื่อตอบคำถามนี้ด้วยความเข้าใจที่ดีที่สุด มีผู้เขียนโปรแกรมที่มีชื่อเสียงสี่คน (Erich Gamma, John Vlissides, Ralph Johnson และ Richard Helm) ที่มาพร้อมกับแนวคิดที่น่าสนใจ พวกเขาสังเกตเห็นว่าการพัฒนาซอฟต์แวร์มักจะต้องแก้ปัญหาเดียวกันโดยประมาณและเขียนโค้ดที่มีโครงสร้างในลักษณะเดียวกัน ดังนั้นพวกเขาจึงตัดสินใจอธิบายรูปแบบทั่วไปที่มักต้องใช้ในการเขียนโปรแกรมเชิงวัตถุ หนังสือของพวกเขาได้รับการตีพิมพ์ในปี 1994 ภายใต้ชื่อ Design Patterns: Elements of Reusable Object-Oriented Software ชื่อหนังสือยาวเกินไปและผู้คนเริ่มเรียกง่ายๆ ว่าหนังสือเล่มนี้โดย Gang of Four รุ่นแรกมี 23 ลาย หลังจากนั้นก็มีการค้นพบรูปแบบอื่นๆ อีกหลายสิบรูปแบบ
รูปแบบการออกแบบเป็นวิธีแก้ปัญหาที่ได้มาตรฐานสำหรับปัญหาทั่วไป
และ รูปแบบ ซิงเกิลตันเป็นเพียงหนึ่งในนั้น

ทำไมเราต้องมีรูปแบบการออกแบบ?

คุณสามารถเขียนโปรแกรมได้โดยไม่ต้องรู้รูปแบบ เพราะเมื่อถึงระดับ 15 คุณได้เขียนโปรแกรมขนาดเล็กหลายร้อยโปรแกรมบน CodeGym โดยที่คุณไม่รู้ด้วยซ้ำว่ามีโปรแกรมเหล่านั้นอยู่ สิ่งนี้ชี้ให้เห็นว่ารูปแบบการออกแบบเป็นเครื่องมือประเภทหนึ่งที่การใช้งานทำให้ผู้เชี่ยวชาญแตกต่างจากมือสมัครเล่น: รูปแบบการออกแบบอธิบายวิธีแก้ปัญหาทั่วไปอย่างเหมาะสม ซึ่งหมายความว่าการรู้รูปแบบจะช่วยคุณประหยัดเวลา ด้วยวิธีนี้ พวกมันคล้ายกับอัลกอริทึม ตัวอย่างเช่น คุณสามารถสร้างอัลกอริทึมการเรียงลำดับของคุณเอง ด้วยแบล็คแจ็คและตัวเลขและใช้เวลามากในการทำเช่นนั้น หรือคุณสามารถนำสิ่งที่เข้าใจและอธิบายไว้นานแล้วไปปฏิบัติ เช่นเดียวกับรูปแบบการออกแบบ นอกจากนี้ ด้วยรูปแบบการออกแบบ โค้ดจะกลายเป็นมาตรฐานมากขึ้น และเมื่อใช้รูปแบบที่เหมาะสม คุณจะมีโอกาสทำผิดพลาดน้อยลง เนื่องจากข้อผิดพลาดทั่วไปของรูปแบบนั้นถูกระบุและกำจัดไปนานแล้ว เหนือสิ่งอื่นใด ความรู้เกี่ยวกับรูปแบบช่วยให้โปรแกรมเมอร์เข้าใจซึ่งกันและกันได้ดีขึ้น คุณสามารถพูดชื่อของรูปแบบแทนการพยายามให้คำอธิบายที่ยืดยาวแก่เพื่อนโปรแกรมเมอร์ของคุณ สรุป รูปแบบการออกแบบช่วยให้คุณ:
  • ไม่คิดค้นล้อขึ้นมาใหม่ แต่ใช้วิธีแก้ไขปัญหามาตรฐานแทน
  • รหัสมาตรฐาน;
  • กำหนดมาตรฐานคำศัพท์
เพื่อสรุปส่วนนี้ เราทราบว่ารูปแบบการออกแบบทั้งหมดสามารถแบ่งออกเป็นสามกลุ่มใหญ่: รูปแบบและซิงเกิล - สำหรับทุกคนที่พบเจอเป็นครั้งแรก - 2

ในที่สุดรูปแบบซิงเกิล

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

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

  2. สร้างคลาสซิงเกิลตันสามคลาส — Sun, Moon, Earth — ในไฟล์แยกกันโดยใช้หลักการเดียวกัน

  3. ดำเนินการดาวเคราะห์อินเตอร์เฟสในคลาสSun , MoonและEarth

  4. ในบล็อกคงที่ของ คลาส Solutionให้เรียกอ่านคีย์จากคอนโซลและอินิตแพลนเน็ตวิธี.

  5. ดำเนินการอ่านคีย์จากคอนโซลและอินิตแพลนเน็ตการทำงานของเมธอด:

    • 5.1. อ่านหนึ่ง พารามิเตอร์ สตริงจากคอนโซล

    • 5.2. ถ้าพารามิเตอร์มีค่าเท่ากับค่าใดค่าหนึ่งดาวเคราะห์ค่าคงที่ของอินเทอร์เฟซ สร้างวัตถุthePlanet ที่เหมาะสม

หลังจากอ่านเงื่อนไขของงานอย่างถี่ถ้วนแล้ว เราจะเห็นได้อย่างชัดเจนว่าเหตุใดSingletonจึงมีความจำเป็นที่นี่ เราถูกขอให้สร้างตัวอย่างของแต่ละคลาสต่อไปนี้: Sun , Moon , Earth มันสมเหตุสมผลแล้วที่จะถือว่าเราควรสร้างดวงอาทิตย์/ดวงจันทร์/โลกไม่เกินหนึ่งดวง มิฉะนั้น เราจะตกอยู่ในสถานการณ์ที่ไร้สาระ เว้นแต่แน่นอนว่าคุณกำลังเขียน Star Wars เวอร์ชันของคุณ การใช้ รูปแบบ Singletonใน Java ในสามขั้นตอน ใน Java พฤติกรรม Singleton ไม่สามารถนำมาใช้โดยใช้ตัวสร้างธรรมดาได้ เนื่องจากตัวสร้างจะส่งคืนวัตถุใหม่เสมอ ดังนั้นการใช้งานSingleton ทั้งหมดเดือดจนซ่อนคอนสตรัคเตอร์ สร้างเมธอดสแตติกสาธารณะที่ควบคุมอายุการใช้งานของออบเจกต์ singleton และ "ทำลาย" ออบเจ็กต์ที่ปรากฏใหม่ทั้งหมด หาก มีการเข้าถึง Singletonควรสร้างวัตถุใหม่ (หากยังไม่มีอยู่ในโปรแกรม) หรือส่งคืนวัตถุที่มีอยู่ เพื่อบรรลุสิ่งนี้:
  1. คุณต้องให้คลาสเป็นฟิลด์สแตติกส่วนตัวที่เก็บวัตถุเดียว:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance; // #1
    }
    
  2. ทำให้ตัวสร้าง (ค่าเริ่มต้น) เป็นส่วนตัว ซึ่งหมายความว่าไม่สามารถเข้าถึงได้นอกชั้นเรียนและจะไม่สามารถส่งคืนวัตถุใหม่ได้:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance;
    private LazyInitializedSingleton(){} // #2
    } 
    
  3. ประกาศวิธีการสร้างแบบคงที่ที่จะใช้เพื่อรับซิงเกิลตัน:

    
    public class LazyInitializedSingleton {
        private static LazyInitializedSingleton instance;
            private LazyInitializedSingleton() {}
            public static LazyInitializedSingleton getInstance() { // #3
            if (instance == null) { // If the object has not yet been created
                instance = new LazyInitializedSingleton(); // Create a new object
            }
            return instance; // Return the previously created object
        }
    }
    
ตัวอย่างข้างต้นค่อนข้างเงอะงะ เนื่องจากเราซ่อนตัวสร้างและจัดเตรียมวิธีการของเราเองแทนที่จะใช้ตัวสร้างมาตรฐาน เนื่องจากบทความนี้มีจุดมุ่งหมายเพื่อให้แน่ใจว่านักเรียน CodeGym ได้สัมผัสกับรูปแบบนี้ (และรูปแบบการออกแบบโดยทั่วไป) ความแตกต่างของการใช้งานซิงเกิลตันที่ซับซ้อนมากขึ้นจะไม่ได้รับการอธิบายไว้ที่นี่ เราทราบเพียงว่ารูปแบบนี้อาจต้องได้รับการปรับปรุงเพิ่มเติม ทั้งนี้ขึ้นอยู่กับความซับซ้อนของโปรแกรม ตัวอย่างเช่น ในสภาพแวดล้อมแบบมัลติเธรด (ดูบทความเกี่ยวกับเธรด) เธรดที่แตกต่างกันหลายเธรดอาจเข้าถึงเมธอดซิงเกิลตันพร้อมกัน และโค้ดที่อธิบายข้างต้นจะหยุดทำงาน เนื่องจากแต่ละเธรดที่แยกกันสามารถสร้างอินสแตนซ์ของคลาสได้ ด้วยเหตุนี้ จึงมีวิธีการต่างๆ มากมายในการสร้างซิงเกิลตันที่ปลอดภัยสำหรับเธรดที่เหมาะสม แต่นั่นเป็นอีกเรื่อง =)

และสุดท้าย... การเริ่มต้นขี้เกียจที่กัปตันถามคืออะไร?

การเริ่มต้นแบบขี้เกียจเรียกอีกอย่างว่าการเริ่มต้นแบบเลื่อนเวลา นี่คือเคล็ดลับการเขียนโปรแกรมที่การดำเนินการที่ใช้ทรัพยากรมาก (และการสร้างวัตถุเป็นการดำเนินการที่ใช้ทรัพยากรมาก) ดำเนินการตามความต้องการแทนที่จะดำเนินการล่วงหน้า แล้วจะเกิดอะไรขึ้นใน โค้ด Singleton Java ของเรา กล่าวอีกนัยหนึ่ง วัตถุของเราถูกสร้างขึ้นตามเวลาที่มีการเข้าถึง ไม่ใช่ล่วงหน้า คุณไม่ควรสันนิษฐานว่าการเริ่มต้นแบบสันหลังยาวนั้นเชื่อมโยงกับรูปแบบSingleton อย่างเหนียวแน่น การเริ่มต้นแบบ Lazy ยังใช้ในรูปแบบการออกแบบเชิงสร้างสรรค์อื่นๆ เช่น Proxy และ Factory Method แต่นี่ก็เป็นอีกเรื่องหนึ่ง =)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION