คุณยังจำได้ไหมว่าพวกอันธพาลให้ความร่วมมือในภาพยนตร์ตำรวจและนักเลงอย่างไร? เมื่อแก๊งค์ลักทรัพย์คนหนึ่งหรือสองคนมักจะพาลมไปที่ประตู หากมีการเคลื่อนไหวใด ๆ ผู้สมรู้ร่วมคิดภายในจะได้รับแจ้งทันทีเพื่อล่าถอยอย่างเร่งด่วน บางทีคนที่ให้ข่าวไม่จำเป็นต้องรู้ว่าทุกคนมีความสมเหตุสมผลในนั้น และอาจมีน้องชายคนใหม่ที่ไม่รู้จักคนที่ปล่อยข่าว แต่นี่คืออะไรมันไม่สามารถส่งผลกระทบต่อการสื่อสารของพวกเขาได้เพราะพวกเขามีรหัสที่ตกลงกันไว้
ฮ่าฮ่าความสัมพันธ์ระหว่างทางอากาศและโจรที่กล่าวถึงข้างต้นเป็นตัวอย่างที่มีชีวิตของรูปแบบผู้สังเกตการณ์ในความเป็นจริง
โหมดผู้สังเกตการณ์เรียกว่าโหมดเผยแพร่/สมัครสมาชิก GOF กำหนดรูปแบบผู้สังเกตการณ์ดังต่อไปนี้: กำหนดการพึ่งพาแบบหนึ่งต่อหลาย ๆ ระหว่างวัตถุ เมื่อสถานะของวัตถุเปลี่ยนแปลงวัตถุทั้งหมดที่ขึ้นอยู่กับมันจะได้รับแจ้งและอัปเดตโดยอัตโนมัติ
ที่นี่ฉันจะพูดคุยเกี่ยวกับหลักการสำคัญของการออกแบบเชิงวัตถุ - หลักการความรับผิดชอบเดียว ดังนั้นแต่ละวัตถุของระบบควรมุ่งเน้นไปที่นามธรรมที่ไม่ต่อเนื่องในโดเมนปัญหา ดังนั้นโดยเฉพาะอย่างยิ่งวัตถุทำสิ่งเดียวเท่านั้น สิ่งนี้นำมาซึ่งประโยชน์มากมายในการพัฒนา: มันให้ความสามารถในการนำกลับมาใช้ใหม่และการบำรุงรักษาและยังเป็นรากฐานที่ดีสำหรับการปรับโครงสร้างใหม่
ดังนั้นรูปแบบการออกแบบเกือบทั้งหมดจึงขึ้นอยู่กับหลักการออกแบบพื้นฐานนี้ ฉันคิดว่าต้นกำเนิดของโมเดลผู้สังเกตการณ์ควรอยู่ในการประมวลผลข้อมูล GUI และข้อมูลทางธุรกิจเนื่องจากตัวอย่างส่วนใหญ่ที่อธิบายรูปแบบผู้สังเกตการณ์ตอนนี้เป็นหัวข้อนี้ อย่างไรก็ตามแอปพลิเคชันของโหมดผู้สังเกตการณ์ไม่ได้ จำกัด อยู่ที่ด้านนี้
ความเข้าใจของคำจำกัดความต้องใช้อินสแตนซ์ในการวิเคราะห์เสมอ บัญชีบริการ WeChat เป็นที่นิยมในปัจจุบัน มาแนะนำรุ่น Observer ให้คุณทราบด้วยพื้นหลังของบัญชีบริการ WeChat
ดูภาพ:
ผู้ใช้แต่ละคนมี 3 บรรทัดในภาพด้านบนซึ่งถูกละเว้นเพื่อให้ภาพชัดเจน
ดังที่แสดงในภาพด้านบนหมายเลขบริการเป็นธีมของเราและผู้ใช้คือผู้สังเกตการณ์ ตอนนี้เราชี้แจงฟังก์ชั่นต่อไปนี้:
1. บัญชีบริการเป็นธีมและธุรกิจกำลังผลักดันข้อความ
2. ผู้สังเกตการณ์จะต้องสมัครรับหัวข้อเท่านั้นและพวกเขาจะถูกส่งทันทีที่มีข่าวใหม่
3. ยกเลิกการสมัครเมื่อคุณไม่ต้องการข้อความหัวข้อนี้
4. ตราบใดที่บัญชีบริการยังคงมีใครบางคนจะถูกสมัครสมาชิก ทีนี้มาดูแผนภาพคลาสของรูปแบบผู้สังเกตการณ์:
ถัดไปคือเวลารหัสเราจำลองบัญชีบริการลอตเตอรี WeChat 3D และสมาชิกบางราย
ก่อนอื่นให้เริ่มเขียนเกี่ยวกับอินเทอร์เฟซหัวข้อและอินเตอร์เฟสผู้สังเกตการณ์:
แพ็คเกจ com.zhy.pattern.observer; / ** * หัวข้ออินเทอร์เฟซหัวข้อทั้งหมดจะต้องใช้อินเทอร์เฟซนี้ * * @author Zhy * */ หัวเรื่องสาธารณะ {/ ** * ลงทะเบียนผู้สังเกตการณ์ * * @param Observer */ Public Void Registerobserver (Observer Observer); / ** * ลบผู้สังเกตการณ์ * * @param Observer */ โมฆะสาธารณะ RemoveObserver (Observer Observer); / *** แจ้งผู้สังเกตการณ์ทั้งหมด*/ โมฆะสาธารณะ NotifyobServers (); } แพ็คเกจ com.zhy.pattern.observer; / *** @author Zhy ผู้สังเกตการณ์ทั้งหมดจำเป็นต้องใช้อินเตอร์เฟสนี้*/ ผู้สังเกตการณ์ส่วนต่อประสานสาธารณะ {การอัปเดตโมฆะสาธารณะ (สตริงผงชูรส); -ระดับการใช้งานหมายเลขบริการ 3 มิติถัดไป:
แพ็คเกจ com.zhy.pattern.observer; นำเข้า java.util.arraylist; นำเข้า java.util.list; Public Class ObjectFor3D ใช้หัวเรื่อง {รายการส่วนตัว <Ebserver> ผู้สังเกตการณ์ = arrayList ใหม่ <Ebserver> (); / *** หมายเลขลอตเตอรี 3D*/ สตริงส่วนตัวข้อความ; @Override โมฆะสาธารณะ registerobserver (Observer Observer) {ผู้สังเกตการณ์ Add (Observer); } @Override โมฆะสาธารณะ removeObserver (Observer Observer) {int index = ผู้สังเกตการณ์ indexof (Observer); if (index> = 0) {ผู้สังเกตการณ์ remove (ดัชนี); }} @Override โมฆะสาธารณะ NotifyObServers () {สำหรับ (Observer Observer: ผู้สังเกตการณ์) {observer.update (msg); }} / ** * ข้อความอัปเดตหัวข้อ * * @param msg * / โมฆะสาธารณะ setmsg (สตริงผงชูรส) {this.msg = msg; NotifyobServers (); -จำลองผู้ใช้สองคน:
แพ็คเกจ com.zhy.pattern.observer; Public Class Observer1 ใช้ผู้สังเกตการณ์ {วิชาส่วนตัว Public Observer1 (หัวเรื่อง) {this.subject = หัวเรื่อง; Subject.registerobserver (นี่); } @Override โมฆะสาธารณะอัปเดต (สตริงผงชูรส) {system.out.println ("observer1 ได้รับหมายเลข 3D ->" + msg + "ฉันต้องการเขียนมันลง"); - แพ็คเกจ com.zhy.pattern.observer; Public Class Observer2 ใช้ผู้สังเกตการณ์ {วิชาส่วนตัว Public Observer2 (หัวเรื่อง) {this.subject = หัวเรื่อง; Subject.registerobserver (นี่); } @Override โมฆะสาธารณะอัปเดต (สตริงผงชูรส) {system.out.println ("observer2 ได้รับหมายเลข 3D ->" + msg + "ฉันต้องการบอกเพื่อนร่วมห้องของฉัน"); - จะเห็นได้ว่าผู้ใช้ทุกคนที่สมัครรับข้อความได้รับการดูแลรักษาไว้ในบัญชีบริการและผู้ใช้ทุกคนจะได้รับแจ้งเมื่อมีข้อความใหม่ในบัญชีบริการ สถาปัตยกรรมทั้งหมดเป็นข้อต่อที่หลวมและการใช้งานของธีมไม่ได้ขึ้นอยู่กับผู้ใช้ เมื่อมีการเพิ่มผู้ใช้ใหม่รหัสของธีมไม่จำเป็นต้องเปลี่ยนแปลง วิธีที่ผู้ใช้ประมวลผลข้อมูลที่ได้รับไม่มีส่วนเกี่ยวข้องกับธีม
ในที่สุดดูรหัสทดสอบ:
แพ็คเกจ com.zhy.pattern.observer.test; นำเข้า com.zhy.pattern.observer.objectfor3d; นำเข้า com.zhy.pattern.observer.observer; นำเข้า com.zhy.pattern.observer.observer1; นำเข้า com.zhy.pattern.observer.observer2; นำเข้า com.zhy.pattern.observer.subject; การทดสอบคลาสสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// จำลองหมายเลขบริการ 3 มิติ ObjectFor3d SubjectFor3d = New ObjectFor3d (); // Customer1 Observer Observer1 = New Observer1 (Subject3d); Observer Observer2 = New Observer2 (SubjectFor3d); SUBJECTFOR3D.SetMSG ("หมายเลข 3D ของ 20140420 คือ: 127"); SUBJECTFOR3D.SETMSG ("20140421 หมายเลข 3D คือ: 333"); -ผลลัพธ์ผลลัพธ์:
Observer1 ได้รับหมายเลข 3D -> หมายเลข 3 มิติของ 20140420 คือ: 127 ฉันต้องการจดบันทึก Observer2 ได้รับหมายเลข 3D -> หมายเลข 3D ของ 20140420 คือ: 127 ฉันต้องการบอกเพื่อนร่วมห้องของฉัน Observer1 ได้รับหมายเลข 3D -> หมายเลข 3 มิติของ 20140421 คือ: 333 ฉันต้องการเขียนลงไป Observer2 ได้รับหมายเลข 3D -> หมายเลข 3D ของ 20140421 คือ: 333 ฉันต้องการบอกเพื่อนร่วมห้องของฉัน
มีหลายสถานที่ใน JDK หรือ Andorid ที่ใช้โหมดผู้สังเกตการณ์เช่น XXXView.addxxxListenter แน่นอน xxxview.setonxxxlistener ไม่จำเป็นต้องเป็นโหมดผู้สังเกตการณ์เนื่องจากโหมดผู้สังเกตการณ์เป็นความสัมพันธ์แบบหนึ่งต่อหลายคน สำหรับ setxxxListener มันเป็นความสัมพันธ์แบบ 1 ต่อ 1 และควรเรียกว่าการโทรกลับ
ขอแสดงความยินดีกับการเรียนรู้โหมดผู้สังเกตการณ์ โหมดผู้สังเกตการณ์ข้างต้นช่วยให้เราสามารถเขียนได้ตั้งแต่เริ่มต้น แน่นอน Java ได้ช่วยให้เราใช้โหมดผู้สังเกตการณ์ด้วยความช่วยเหลือของ java.util.observable และ java.util.observer
ด้านล่างเราใช้คลาส Java ในตัวเพื่อใช้รูปแบบผู้สังเกตการณ์:
ก่อนอื่นมีชุดรูปแบบหมายเลขบริการลอตเตอรี 3 มิติ:
แพ็คเกจ com.zhy.pattern.observer.java; นำเข้า java.util.observable; ชั้นเรียนสาธารณะ SUNCTHON3D ขยายการสังเกต {Private String MSG; สตริงสาธารณะ getmsg () {return msg; } / ** * ข้อความอัปเดตหัวข้อ * * @param msg * / โมฆะสาธารณะ setmsg (สตริงผงชูรส) {this.msg = msg; setchanged (); NotifyobServers (); -ต่อไปนี้เป็นธีมของหมายเลขบริการลูกสีสองเท่า:
แพ็คเกจ com.zhy.pattern.observer.java; นำเข้า java.util.observable; Public Class PresentForSSQ ขยายการสังเกต {Private String MSG; สตริงสาธารณะ getmsg () {return msg; } / ** * ข้อความอัปเดตหัวข้อ * * @param msg * / โมฆะสาธารณะ setmsg (สตริงผงชูรส) {this.msg = msg; setchanged (); NotifyobServers (); -ในที่สุดผู้ใช้ของเรา:
แพ็คเกจ com.zhy.pattern.observer.java; นำเข้า java.util.observable; นำเข้า java.util.observer; Public Class Observer1 ใช้ผู้สังเกตการณ์ {โมฆะสาธารณะลงทะเบียน (สังเกตได้สังเกตได้) {สังเกตได้ AdDoBserver (นี่); } @Override การอัปเดตโมฆะสาธารณะ (สังเกต o, Object arg) {ถ้า (O Instanceof SubjectFor3d) {subjectFor3d SubjectFor3d = (subjectFor3d) o; System.out.println ("MSG ของ SUBNYFOR3D ->" + SUNCTIONFOR3D.GETMSG ()); } if (o instanceof unduleforssq) {underialforssq unduleforssq = (ubsementforssq) o; System.out.println ("unduceforssq ของข้อความ ->" + unduleforssq.getmsg ()); -ดูรหัสทดสอบ:
แพ็คเกจ com.zhy.pattern.observer.java; การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {subjectfor3d subjectfor3d = new SubjectFor3d (); SubjectForSSQ SubjectForSSQ = New SubjectForSSQ (); observer1 observer1 = New Observer1 (); Observer1.registersubject (Subject3d); Observer1.registersubject (SubjectForSSQ); subjectfor3d.setmsg ("สวัสดี 3d'nums: 110"); SubjectForSSQ.SetMSG ("SSQ'Nums: 12,13,31,5,4,3 15"); -ผลการทดสอบ:
MSG ของ SubjectFor3D -> Hello 3d'Nums: 110 MSG SUBSIONSSQ -> SSQ'Nums: 12,13,31,5,4,3 15 15 15
จะเห็นได้ว่าการใช้คลาส Java ในตัวเพื่อใช้รูปแบบผู้สังเกตการณ์รหัสนั้นกระชับมาก โดยวิธีการที่ Addobserver, RemoveObserver, NotifyobServers ได้ถูกนำไปใช้สำหรับเรา ทั้งหมดที่เราเห็นได้ว่าการสังเกตคือคลาสไม่ใช่อินเทอร์เฟซ โดยพื้นฐานแล้วหนังสือเล่มนี้มีทัศนคติเชิงลบต่อการออกแบบของ Java รู้สึกว่ารูปแบบผู้สังเกตการณ์ในตัวของ Java ละเมิดหลักการของการเขียนโปรแกรมเชิงอินเตอร์เฟส อย่างไรก็ตามหากคุณคิดเกี่ยวกับมันคุณกำลังเขียนรูปแบบผู้สังเกตการณ์ที่นี่ (การใช้งานของเราเอง) แนวคิดอินเทอร์เฟซนั้นดีมาก แต่ถ้าคุณยังคงเพิ่มหัวข้อมากมายในตอนนี้ DDOBServer, RemoveObserver, NotifyObServers สำหรับแต่ละหัวข้อนั้นเหมือนกัน อินเทอร์เฟซไม่สามารถใช้การใช้รหัสซ้ำได้และไม่มีวิธีใช้โหมดรวมกันเพื่อให้ได้การนำกลับมาใช้ใหม่ทั้งสามวิธีดังนั้นฉันคิดว่ามันสมเหตุสมผลที่จะใช้วิธีการทั้งสามนี้ในชั้นเรียนที่นี่