คำจำกัดความ: อนุญาตให้วัตถุหลายชิ้นมีโอกาสประมวลผลคำขอดังนั้นจึงหลีกเลี่ยงความสัมพันธ์ระหว่างผู้ส่งและผู้รับของคำขอ เชื่อมต่อวัตถุเหล่านี้เข้ากับโซ่และส่งคำขอไปตามห่วงโซ่จนกว่าวัตถุจะประมวลผล
ประเภท: รูปแบบพฤติกรรม
แผนภาพชั้นเรียน:
ก่อนอื่นให้ดูที่รหัสชิ้นหนึ่ง:
การทดสอบโมฆะสาธารณะ (int i คำขอ) {ถ้า (i == 1) {handler1.Response (คำขอ); } อื่นถ้า (i == 2) {handler2.Response (คำขอ); } อื่นถ้า (i == 3) {handler3.Response (คำขอ); } อื่นถ้า (i == 4) {handler4.Response (คำขอ); } else {handler5.Response (คำขอ); - ตรรกะทางธุรกิจของรหัสมีดังนี้: วิธีการมีสองพารามิเตอร์: จำนวนเต็ม I และคำขอคำขอ ตามค่าของฉันใครจะจัดการกับคำขอถ้าฉัน == 1 มันจะได้รับการจัดการโดย Handler1 ถ้า i == 2 มันจะได้รับการจัดการโดย Handler2 และอื่น ๆ ในการเขียนโปรแกรมวิธีการประมวลผลธุรกิจประเภทนี้เป็นเรื่องธรรมดามาก คลาสทั้งหมดที่กระบวนการร้องขอรวมถึงถ้า ... อื่น ... งบการตัดสินตามเงื่อนไขที่เชื่อมต่อเป็นห่วงโซ่ความรับผิดชอบในการประมวลผลคำขอ ฉันเชื่อว่าทุกคนมักใช้มัน ข้อดีของวิธีนี้คือมันเป็นเรื่องง่ายง่ายและชัดเจนและค่อนข้างง่ายต่อการบำรุงรักษา แต่วิธีนี้ก็มีอาการปวดหัวหลายอย่างด้วย:
Code Bloated: ในแอปพลิเคชันจริงเงื่อนไขการตัดสินมักจะไม่ง่ายนักที่จะพิจารณาว่าเป็น 1 หรือ 2 มันอาจต้องใช้การคำนวณที่ซับซ้อนหรืออาจสอบถามฐานข้อมูล ฯลฯ นี้จะมีรหัสเพิ่มเติมมากมาย หากมีเงื่อนไขการตัดสินมากมายถ้า ... อื่น ... คำแถลงนั้นเป็นไปไม่ได้ที่จะอ่าน
ระดับการมีเพศสัมพันธ์สูง: หากเราต้องการเพิ่มคลาสที่ดำเนินการตามคำขอเราจะต้องเพิ่มอย่างอื่นหากเงื่อนไขการตัดสิน; นอกจากนี้ลำดับของเงื่อนไขนี้ยังเขียนถึงคนตาย หากเราต้องการเปลี่ยนคำสั่งซื้อเราสามารถแก้ไขคำสั่งเงื่อนไขนี้ได้เท่านั้น
เนื่องจากเราเข้าใจข้อบกพร่องแล้วเราจึงต้องหาวิธีแก้ปัญหาพวกเขา ตรรกะทางธุรกิจของสถานการณ์นี้ง่ายมาก: หากเป็นไปตามเงื่อนไข 1 มันจะถูกประมวลผลโดย Handler1 และหากไม่ตรงกับมันจะถูกส่งผ่าน หากพบกับเงื่อนไข 2 มันจะถูกประมวลผลโดย Handler2 และหากไม่ตรงกับมันจะถูกส่งผ่านลงไปจนถึงจุดสิ้นสุดของเงื่อนไข ในความเป็นจริงวิธีการปรับปรุงนั้นง่ายมากเช่นกันซึ่งก็คือการทำให้ส่วนหนึ่งของเงื่อนไขการตัดสินลงในคลาสการประมวลผล นี่คือหลักการของรูปแบบการเชื่อมต่อความรับผิดชอบ
โครงสร้างของรูปแบบ บริษัท รับผิดชอบ
แผนภาพคลาสของรูปแบบที่เชื่อมต่อกับความรับผิดชอบนั้นง่ายมากมันประกอบด้วยคลาสที่ผ่านการประมวลผลแบบนามธรรมและชุดของคลาสการใช้งาน:
บทคัดย่อคลาสการประมวลผล: คลาสการประมวลผลนามธรรมส่วนใหญ่รวมถึงตัวแปรสมาชิก Nexthandler ชี้ไปที่คลาสการประมวลผลถัดไปและวิธีการจัดการที่จัดการกับคำขอ แนวคิดหลักของวิธี HandRequest คือหากเป็นไปตามเงื่อนไขการประมวลผลคลาสการประมวลผลนี้จะถูกประมวลผลมิฉะนั้นจะถูกประมวลผลโดย NexThandler
คลาสการประมวลผลเฉพาะ: คลาสการประมวลผลเฉพาะส่วนใหญ่ใช้ตรรกะการประมวลผลเฉพาะและเงื่อนไขที่ใช้สำหรับการประมวลผล
ตัวอย่าง
รูปแบบห่วงโซ่ความรับผิดชอบมีสองบทบาท:
บทคัดย่อตัวจัดการบทบาท: กำหนดอินเทอร์เฟซที่ร้องขอ หากจำเป็นคุณสามารถกำหนดวิธีการตั้งค่าและส่งคืนการอ้างอิงไปยังวัตถุบ้านถัดไป
ConcreteHandler บทบาท: หากสามารถประมวลผลได้ให้ประมวลผลคำขอ หากไม่สามารถดำเนินการได้ให้ส่งคำขอไปยังบ้านถัดไปและปล่อยให้บ้านถัดไปจัดการกับมัน กล่าวคือมันจัดการคำขอที่สามารถจัดการและสามารถเข้าถึงบ้านถัดไปได้
รหัสทดสอบสำหรับรูปแบบข้างต้นมีดังนี้:
แพ็คเกจ chainofresp;/***คำอธิบาย: บทคัดย่อบทบาทการประมวลผล*/ตัวจัดการคลาสนามธรรมสาธารณะ {ผู้สืบทอดผู้สืบทอดการป้องกัน; / ***คำอธิบาย: วิธีการประมวลผล*/ บทคัดย่อสาธารณะเป็นโมฆะ HandlerRequest (เงื่อนไขสตริง); ตัวจัดการสาธารณะ getSuccessor () {ผู้สืบทอดกลับ; } โมฆะสาธารณะ setSuccessor (ผู้สืบทอดผู้สืบทอด) {this.successor = ผู้สืบทอด; - แพ็คเกจ chainofresp;/***คำอธิบาย: การจัดการอย่างละเอียดของบทบาท*/คลาสสาธารณะ ConcreteHandler1 ขยายตัวจัดการ {@Override โมฆะโมฆะ public HandlerRequest (เงื่อนไขสตริง) {// ถ้าเป็นความรับผิดชอบของคุณเอง - กลับ ; } else {system.out.println ("ConcreteHandler1 ผ่าน"); GetSuccessor (). HandlerRequest (เงื่อนไข); }}} แพ็คเกจ chainofresp;/***คำอธิบาย: การจัดการอย่างละเอียดของบทบาท*/คลาสสาธารณะ ConcreteHandler2 ขยายตัวจัดการ {@Override โมฆะโมฆะ public HandlerRequest (เงื่อนไขสตริง) {// ถ้าเป็นความรับผิดชอบของคุณเอง - กลับ ; } else {system.out.println ("ConcreteHandler2 ผ่าน"); GetSuccessor (). HandlerRequest (เงื่อนไข); }}} แพ็คเกจ chainofresp;/*** คำอธิบาย: บทบาทการประมวลผลโดยละเอียด*/คลาสสาธารณะคอนกรีตแฮนด์เลิร์นขยายตัวจัดการ {/*** ที่นี่สันนิษฐานว่า n เป็นโหนดสุดท้ายของห่วงโซ่ที่ต้องประมวลผล* ในสถานการณ์จริงแหวนหรือต้นไม้อาจปรากฏขึ้น* นี่ไม่จำเป็นต้องเป็นโหนดสุดท้าย * */ @Override โมฆะสาธารณะ HandlerRequest (เงื่อนไขสตริง) {System.out.println ("ConcreteHandlern Handled"); - แพ็คเกจ chainofresp;/***คำอธิบาย: คลาสทดสอบ*/ไคลเอนต์คลาสสาธารณะ {/***คำอธิบาย:*/โมฆะคงที่สาธารณะหลัก (สตริง [] args) {handler handler1 = ใหม่ ConcreteHandler1 (); handler handler2 = ใหม่ ConcreteHandler2 (); handler handlern = ใหม่ ConcreteHandlern (); // Chain Handler1.setsuccessor (Handler2); handler2.setsuccessor (handlern); // สมมติว่าคำขอนี้เป็นความรับผิดชอบของ ConcreteHandler2 Handler1.HandlerRequest ("ConcreteHandler2"); -
เพื่อให้ตัวอย่างนี้ในการประชุมเชิงปฏิบัติการการผลิตของโรงงานของเล่นสายการประกอบเป็นห่วงโซ่ความรับผิดชอบ หากเครื่องบินของเล่นมีแอสเซมเบลอร์, แอสเซมเบลอร์เครื่องยนต์, แอสเซมเบลอร์ใบพัดและโมเดลแพคเกอร์ เมื่อเครื่องบินไหลไปยังใครก็ตามที่วัตถุกำลังไหลเขาจะต้องรับผิดชอบในการติดตั้งส่วนที่เขารับผิดชอบ หลังจากติดตั้งส่วนนี้มันจะไหลไปยังขั้นตอนต่อไปและรู้ว่าสภาพแวดล้อมทั้งหมดเสร็จสมบูรณ์ นี่คือห่วงโซ่ของความรับผิดชอบที่สร้างขึ้น นอกจากนี้ยังมีห่วงโซ่การตรวจสอบคุณภาพซึ่งแบ่งออกเป็นหลายส่วนการตรวจสอบเปลือกการตรวจสอบเครื่องยนต์การตรวจสอบใบพัดและการตรวจสอบบรรจุภัณฑ์ เมื่อผลิตภัณฑ์ถูกทิ้งไว้กับผู้ตรวจสอบเพื่อทดสอบชิ้นส่วนที่เขารับผิดชอบหากมีปัญหาใด ๆ มันจะถูกนำออกไปโดยตรง หากไม่มีปัญหาจะถูกส่งผ่านไปยังผู้ตรวจสอบคนต่อไปจนกว่าการทดสอบทั้งหมดจะเสร็จสิ้น ทั้งสองนี้เป็นโซ่แห่งความรับผิดชอบ แต่ความแตกต่างคือทุกคนจะประมวลผลห่วงโซ่ความรับผิดชอบและกระบวนการของมัน ในขณะที่หลังจากการตัดสินห่วงโซ่ความรับผิดชอบในการตรวจสอบคุณภาพจะได้รับการประมวลผลหรือไม่ประมวลผล นี่คือโซ่ความรับผิดชอบสองประเภท หลังเรียกว่าโซ่ความรับผิดชอบบริสุทธิ์และอดีตเรียกว่าโซ่ความรับผิดชอบที่ไม่บริสุทธิ์ โซ่ความรับผิดชอบบริสุทธิ์ไม่ค่อยมีอยู่ในการใช้งานจริง คนทั่วไปคือโซ่ความรับผิดชอบที่ไม่บริสุทธิ์ โมเดลข้างต้นจำลองโซ่ความรับผิดชอบบริสุทธิ์ที่จะจัดการ
ข้อดีและข้อเสียของรูปแบบห่วงโซ่ความรับผิดชอบ
เมื่อเทียบกับถ้า…อื่น…รูปแบบห่วงโซ่ความรับผิดชอบมีความสามารถในการมีเพศสัมพันธ์ที่ต่ำกว่าเพราะมันกระจายการตัดสินตามเงื่อนไขไปยังคลาสการประมวลผลที่หลากหลายและลำดับการประมวลผลลำดับความสำคัญของคลาสการประมวลผลเหล่านี้สามารถตั้งค่าได้ รูปแบบห่วงโซ่ความรับผิดชอบยังมีข้อเสียซึ่งเป็นเช่นเดียวกับคำสั่งถ้า ... อื่น ... นั่นคือก่อนที่จะค้นหาคลาสการประมวลผลที่ถูกต้องเงื่อนไขการตัดสินทั้งหมดจะต้องดำเนินการ เมื่อห่วงโซ่ความรับผิดชอบค่อนข้างยาวปัญหาประสิทธิภาพจะรุนแรงขึ้น
สถานการณ์ที่ใช้งานได้สำหรับรูปแบบความรับผิดชอบ
เช่นเดียวกับตัวอย่างเริ่มต้นหากคุณรู้สึกว่าถูกครอบงำเมื่อใช้คำสั่ง IF …อื่น…เพื่อจัดระเบียบห่วงโซ่ความรับผิดชอบและรหัสดูไม่ดีคุณสามารถใช้โหมดความรับผิดชอบในการปรับเปลี่ยนใหม่
สรุป
แบบจำลองห่วงโซ่ความรับผิดชอบเป็นเวอร์ชันที่ยืดหยุ่นของ IF ... อื่น ... คำสั่ง มันทำให้เงื่อนไขการตัดสินเหล่านี้ลงในแต่ละคลาสการประมวลผล ข้อดีของสิ่งนี้คือมันมีความยืดหยุ่นมากขึ้น แต่ก็นำมาซึ่งความเสี่ยง ตัวอย่างเช่นเมื่อตั้งค่าความสัมพันธ์ระหว่างคลาสการประมวลผลก่อนและหลังคลาสการประมวลผลคุณต้องระมัดระวังอย่างมากในการตัดสินความสัมพันธ์ระหว่างตรรกะตามเงื่อนไขก่อนและหลังคลาสการประมวลผลและระวังไม่ให้มีการอ้างอิงแบบวงกลมในห่วงโซ่