เหตุใด ShapeFactory นี้จึงใช้คำสั่งแบบมีเงื่อนไขเพื่อกำหนดว่าวัตถุใดที่จะยกตัวอย่าง เราไม่จำเป็นต้องปรับเปลี่ยน ShapeFactory หากเราต้องการเพิ่มคลาสอื่น ๆ ในอนาคตหรือไม่ ทำไมสิ่งนี้ถึงไม่ละเมิดหลักการเปิดที่เปิดอยู่?
เหตุใด ShapeFactory นี้จึงใช้คำสั่งแบบมีเงื่อนไขเพื่อกำหนดว่าวัตถุใดที่จะยกตัวอย่าง เราไม่จำเป็นต้องปรับเปลี่ยน ShapeFactory หากเราต้องการเพิ่มคลาสอื่น ๆ ในอนาคตหรือไม่ ทำไมสิ่งนี้ถึงไม่ละเมิดหลักการเปิดที่เปิดอยู่?
คำตอบ:
ภูมิปัญญาเชิงวัตถุแบบดั้งเดิมคือการหลีกเลี่ยงif
คำสั่งและแทนที่ด้วยการแจกจ่ายวิธีการเขียนทับแบบไดนามิกในคลาสย่อยของคลาสนามธรรม จนถึงตอนนี้ดีมาก
แต่ประเด็นสำคัญของรูปแบบของโรงงานคือการช่วยให้คุณไม่ต้องรู้เกี่ยวกับคลาสย่อยแต่ละอันและทำงานกับซูเปอร์คลาสนามธรรมเท่านั้น แนวคิดคือโรงงานรู้ดีกว่าคุณว่าคลาสใดที่จะยกตัวอย่างและคุณจะทำงานได้ดีขึ้นเมื่อใช้วิธีการที่เผยแพร่โดยซุปเปอร์คลาสเท่านั้น นี่เป็นเรื่องจริงและเป็นรูปแบบที่มีค่า
ดังนั้นจึงไม่มีวิธีใดที่การเขียนคลาสของโรงงานสามารถนำมาใช้กับif
ข้อความได้ มันจะเปลี่ยนภาระของการเลือกเรียนเฉพาะการโทรซึ่งเป็นว่าสิ่งที่รูปแบบที่ควรจะหลีกเลี่ยง ไม่หลักการทั้งหมดที่มีสัมบูรณ์ (ในความเป็นจริงไม่มีหลักการที่แน่นอน) if
และถ้าคุณใช้รูปแบบนี้คุณจะคิดว่าได้รับประโยชน์จากมันมากกว่าประโยชน์ของไม่ได้ใช้นั้น
if
s จำนวนมาก ดูคำตอบของ@BЈовићสำหรับตัวอย่างง่ายๆของการบรรลุสิ่งนี้ downvoted
ตัวอย่างอาจใช้คำสั่งแบบมีเงื่อนไขเนื่องจากเป็นแบบที่ง่ายที่สุด การนำไปใช้ที่ซับซ้อนมากขึ้นอาจใช้แผนที่หรือการกำหนดค่าหรือ (ถ้าคุณต้องการแฟนซีมาก) สตรีบางประเภทที่คลาสสามารถลงทะเบียนตัวเองได้ อย่างไรก็ตามไม่มีอะไรผิดปกติกับการใช้เงื่อนไขหากจำนวนชั้นเรียนมีขนาดเล็กและเปลี่ยนแปลงไม่บ่อยนัก
การขยายเงื่อนไขเพื่อเพิ่มการสนับสนุนสำหรับคลาสย่อยใหม่ในอนาคตแน่นอนว่าการพูดอย่างเคร่งครัดเป็นการละเมิดหลักการเปิด / ปิด โซลูชัน "ถูกต้อง" จะสร้างโรงงานใหม่ด้วยอินเทอร์เฟซเดียวกัน ที่กล่าวว่าการยึดมั่นในหลักการ O / C ควรคำนึงถึงหลักการออกแบบอื่น ๆ เช่น KISS และ YAGNI เสมอ
ที่กล่าวว่ารหัสที่แสดงเป็นตัวอย่างรหัสที่ชัดเจนซึ่งออกแบบมาเพื่อแสดงแนวคิดของโรงงานและไม่มีอะไรอื่น เช่นมันเป็นสไตล์ที่ไม่ดีจริง ๆ ที่จะคืนค่าว่างเปล่าตามตัวอย่าง แต่การจัดการข้อผิดพลาดที่ซับซ้อนกว่านั้นจะคลุมเครือในจุดนั้น โค้ดตัวอย่างไม่ใช่รหัสคุณภาพการผลิตใด ๆ ที่คุณไม่ควรคาดหวัง
รูปแบบนั้นไม่ได้ละเมิดหลักการ Open / Closed (OCP) อย่างไรก็ตามเราละเมิด OCP เมื่อเราใช้รูปแบบที่ไม่ถูกต้อง
คำตอบง่ายๆสำหรับคำถามนี้มีดังนี้:
ในตัวอย่างที่ให้มาฟังก์ชันการทำงานพื้นฐานของคุณรองรับสามรูปร่าง: วงกลมสี่เหลี่ยมผืนผ้าและสี่เหลี่ยม สมมติว่าคุณต้องการรองรับ Triangle, Pentagon และ Hexagon ในอนาคต ในการทำเช่นนี้โดยไม่ละเมิด OCP คุณต้องสร้างโรงงานเพิ่มเติมเพื่อสนับสนุนรูปร่างใหม่ของคุณ (เรียกว่าAdvancedShapeFactory
) จากนั้นใช้AbstractFactoryเพื่อตัดสินใจโรงงานที่คุณต้องการสร้างเพื่อสร้างรูปร่างใด ๆ ที่คุณต้องการ
หากคุณกำลังพูดถึงรูปแบบนามธรรมจากโรงงานการตัดสินใจมักจะไม่ได้อยู่ในตัวโรงงาน แต่อยู่ในรหัสแอปพลิเคชัน เป็นรหัสที่เลือกโรงงานคอนกรีตเพื่อยกตัวอย่างและส่งต่อไปยังรหัสลูกค้าที่จะใช้วัตถุที่ผลิตโดยโรงงาน ดูจุดสิ้นสุดของตัวอย่าง Java ที่นี่: https://en.wikipedia.org/wiki/Abstract_factory_pattern
การตัดสินใจไม่จำเป็นต้องหมายถึงif
งบ มันสามารถอ่านประเภทโรงงานคอนกรีตจากไฟล์กำหนดค่าสืบทอดมาจากโครงสร้างแผนที่ ฯลฯ
หากคุณคิดว่า Open-Close ที่ระดับคลาสกับโรงงานนี้คุณกำลังสร้างคลาสอื่นในระบบ Open-Close ของคุณตัวอย่างเช่นถ้าคุณมีคลาสอื่นที่มีรูปร่างเดียวและคำนวณพื้นที่ (ตัวอย่างทั่วไป) คลาสนี้เป็น OpenClose เพราะ มันสามารถคำนวณพื้นที่สำหรับรูปร่างชนิดใหม่โดยไม่ต้องดัดแปลง จากนั้นคุณมีคลาสอื่นที่ดึงรูปร่างอีกคลาสที่ใช้รูปร่าง N และส่งคืนคลาสที่ใหญ่กว่าและคุณสามารถคิดโดยทั่วไปว่าคลาสอื่น ๆ ในระบบของคุณที่จัดการกับรูปร่างนั้นเป็น Open-Close (อย่างน้อยเกี่ยวกับรูปร่าง) เมื่อมองที่การออกแบบโรงงานจะทำให้ระบบที่เหลือเป็นแบบเปิด - ปิดและแน่นอนว่าตัวโรงงานเองไม่เปิด - ปิด
นอกหลักสูตรคุณสามารถเปิดโรงงานนี้ด้วยการโหลดแบบไดนามิกบางชนิดและระบบทั้งหมดของคุณสามารถเป็นแบบเปิดปิด (คุณสามารถเพิ่มรูปร่างใหม่ที่วางขวดบางขวดใน classpath เป็นต้น) คุณจำเป็นต้องประเมินความซับซ้อนพิเศษนี้มีค่าขึ้นอยู่กับระบบที่คุณกำลังสร้างไม่ใช่ทุกระบบที่ต้องการคุณสมบัติที่เสียบได้และไม่ใช่ทุกระบบที่จะต้องเปิดอย่างสมบูรณ์
หลักการแบบเปิดปิดในฐานะหลักการทดแทน Liskov นำไปใช้กับต้นไม้ในชั้นเรียนเพื่อลำดับชั้นการสืบทอด ในตัวอย่างของคุณคลาสโรงงานไม่ได้อยู่ในแผนภูมิต้นไม้ของคลาสที่เป็นอินสแตนซ์ดังนั้นจึงไม่สามารถละเมิดกฎเหล่านี้ได้ จะมีการละเมิดหากมีการใช้งาน GetShape (หรือชื่อที่เหมาะเจาะกว่านั้นคือ CreateShape) ในคลาสฐานรูปร่าง
ทุกอย่างขึ้นอยู่กับว่าคุณใช้มันอย่างไร คุณสามารถใช้std::map
เพื่อเก็บตัวชี้ฟังก์ชั่นกับฟังก์ชั่นการสร้างวัตถุ จากนั้นหลักการเปิด / ปิดจะไม่ถูกละเมิด หรือสลับ / กรณี
อย่างไรก็ตามหากคุณไม่ชอบรูปแบบของโรงงานคุณสามารถใช้การฉีดแบบพึ่งพาได้เสมอ