ผู้ฟังเหตุการณ์ควรจัดขึ้นในการอ้างอิงที่อ่อนแอ?


9

โดยทั่วไปผู้ฟังเหตุการณ์ไม่ควรอยู่เหนือกว่าวัตถุที่ลงทะเบียนไว้

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

มีกรณีที่ถูกต้องหรือไม่เมื่อผู้ฟังควรมีอายุยืนกว่าผู้สร้าง

หรืออาจเป็นเช่นนั้นเป็นความผิดพลาดและไม่ควรอนุญาต


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

คำตอบ:


7

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

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

  • ง่ายต่อการสร้างโดยไม่ได้ตั้งใจ (สิ่งที่คุณต้องทำคือลืมเก็บวัตถุไว้ในตัวแปรอ้างอิงที่คุณไม่เคยใช้)
  • สังเกตได้ยาก (คุณจะได้รับบั๊กนั้นก็ต่อเมื่อ GC รวบรวมวัตถุนั้น)
  • ยากที่จะดีบั๊ก (ในเซสชันการดีบัก - ซึ่งใช้งานได้เหมือนเซสชันที่วางจำหน่าย - คุณจะพบข้อบกพร่องนั้นเท่านั้นหาก GC รวบรวมวัตถุ)

และหากหลีกเลี่ยงข้อผิดพลาดนั้นไม่ดีพอแรงจูงใจนี่คือบางส่วนเพิ่มเติม:

  1. คุณจะต้องคิดถึงชื่อสำหรับผู้ฟังแต่ละคนที่คุณสร้าง

  2. บางภาษาใช้การกำจัดกระแสไฟฟ้าสถิตย์ที่จะสร้างคำเตือนหากคุณมีเขตข้อมูลสมาชิกส่วนตัวที่ไม่เคยเขียนหรือไม่เคยอ่าน คุณจะต้องใช้มีกลไกในการเอาชนะมัน

  3. ผู้ฟังเหตุการณ์ทำอะไรบางอย่างและเมื่อมีการรวบรวมวัตถุที่มีการอ้างอิงที่รัดกุมแล้วจะหยุดทำสิ่งนั้น ตอนนี้คุณมีบางสิ่งที่ส่งผลกระทบต่อสถานะของโปรแกรมและขึ้นอยู่กับ GC - ซึ่งหมายความว่า GC ส่งผลกระทบต่อสถานะที่เป็นรูปธรรมของโปรแกรม และนี่คือBAD !

  4. การจัดการการอ้างอิงที่อ่อนแอจะช้าลงเนื่องจากคุณมีระดับการอ้อมอีกระดับและเนื่องจากคุณต้องตรวจสอบว่ามีการรวบรวมการอ้างอิงหรือไม่ สิ่งนี้จะไม่เป็นปัญหาหากการมีผู้ฟังเหตุการณ์ในการอ้างอิงอ่อน ๆ เป็นสิ่งที่จำเป็น - แต่ไม่ใช่


5

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

เรียกกลับ

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

promise =
    Promise.new(async_task)                # - kick off a task
    .then(value => operation_on(value))    # - queue other operations
    .then(value => other_operation(value)) #   that get executed on completion
... # do other stuff in the meanwhile
# later:
result = promise.value # block for the result

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

รูปแบบการสังเกตการณ์

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

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

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

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

  • ทำด้วยตนเอง แต่มีแนวโน้มที่จะเกิดข้อผิดพลาด

  • ใช้สิ่งที่คล้ายกับลองกับทรัพยากรใน Java หรือusingใน C #

  • การทำลายล้างที่กำหนดขึ้นเช่นผ่านทาง RAII สำนวน โปรดทราบว่าในภาษาที่มีการรวบรวมขยะที่กำหนดค่าได้สิ่งนี้อาจยังต้องมีการอ้างอิงที่ไม่ชัดเจนจากผู้ทดสอบไปยังผู้สังเกตการณ์เพื่อให้เกิดการทำลาย

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