ภาพรวมอย่างรวดเร็ว
โซลูชันที่ 3: รูปแบบการออกแบบซอฟต์แวร์ "Parallel Class Hierarchy" เป็นเพื่อนของคุณ
คำตอบที่ยาวนาน
การออกแบบของคุณเริ่มต้นแล้ว มันสามารถปรับให้เหมาะสมชั้นเรียนหรือสมาชิกบางคนอาจถูกลบออก แต่ความคิด "ลำดับชั้นขนาน" ที่คุณใช้ในการแก้ปัญหาคือขวา
มีการจัดการกับแนวคิดเดียวกันหลายครั้งมักจะอยู่ในลำดับชั้นการควบคุม
หลังจากนั้นไม่นานฉันก็ลงเอยด้วยการแก้ปัญหาที่เหมือนกันกว่านักพัฒนาอื่น ๆ ซึ่งบางครั้งเรียกว่ารูปแบบการออกแบบ "ลำดับชั้นคู่ขนาน" หรือรูปแบบการออกแบบ "ลำดับคู่คู่"
(1) คุณเคยแบ่งคลาสเดี่ยวเป็นลำดับชั้นของชั้นเดียวหรือไม่?
(2) คุณเคยแบ่งชั้นหนึ่งเป็นหลายชั้นโดยไม่มีลำดับชั้นหรือไม่?
หากคุณได้ใช้วิธีแก้ไขปัญหาก่อนหน้านี้แยกจากกันเป็นวิธีแก้ปัญหาบางอย่าง
แต่ถ้าเรารวมสองโซลูชั่นนี้พร้อมกันล่ะ
รวมเข้าด้วยกันและคุณจะได้รับ "รูปแบบการออกแบบ" นี้
การดำเนินงาน
ตอนนี้มาปรับใช้รูปแบบการออกแบบซอฟต์แวร์ "Parallel Class Hierarchy" กับกรณีของคุณ
ขณะนี้คุณมีลำดับชั้นของคลาสอย่างน้อย 2 คลาสที่คล้ายกันมากมีการเชื่อมโยงหรือ purpouse ที่คล้ายกันมีคุณสมบัติหรือวิธีการที่คล้ายกัน
คุณต้องการหลีกเลี่ยงการมีรหัสซ้ำหรือสมาชิก ("ความสอดคล้อง") แต่คุณไม่สามารถรวมคลาสนี้เข้าเป็นหนึ่งเดียวได้โดยตรงเนื่องจากความแตกต่างระหว่างพวกเขา
ดังนั้นลำดับชั้นของคุณคล้ายกันมากกับรูปนี้ แต่ยังมีมากกว่าหนึ่ง:
................................................
...............+----------------+...............
...............| Common:: |...............
...............| Composite |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
...............+-------+--------+...............
...............| Common:: |...............
...............| Viewee |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Common:: |........| Common:: |..
..| Visual |........| Structural |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 1
ในเรื่องนี้ยังไม่ได้รับการรับรองรูปแบบการออกแบบชุดการตรวจสอบหลายตำแหน่งถูกรวมเข้าด้วยกันเป็นระบบเดียวและแต่ละคลาสที่แชร์หรือทั่วไปจะถูกขยายโดยคลาสย่อย
โปรดทราบว่าการแก้ปัญหานี้มีความซับซ้อนเพราะคุณกำลังจัดการกับหลายลำดับชั้นแล้วจึงเป็นสถานการณ์ที่ซับซ้อน
1 คลาสรูต
ในแต่ละลำดับชั้นจะมีคลาส "root" ที่ใช้ร่วมกัน
ในกรณีของคุณมีคลาส "คอมโพสิต" อิสระสำหรับแต่ละลำดับชั้นที่สามารถมีคุณสมบัติที่คล้ายกันและวิธีการที่คล้ายกันบางอย่าง
สมาชิกบางคนสามารถรวมกันได้บางส่วนของสมาชิกเหล่านั้นไม่สามารถรวมได้
ดังนั้นสิ่งที่นักพัฒนาสามารถทำได้คือการทำให้คลาสรูทฐานและคลาสย่อยเป็นกรณีที่เทียบเท่าสำหรับแต่ละลำดับชั้น
ในรูปที่ 2 คุณสามารถเห็นไดอะแกรมสำหรับคลาสนี้ซึ่งแต่ละคลาสเก็บไว้ที่เนมสเปซ
สมาชิกจะถูกละไว้โดยขณะนี้
................................................
...............+-------+--------+...............
...............| Common:: |...............
...............| Composite |...............
...............+----------------+...............
...............| ... |...............
...............+-------+--------+...............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Composite |........| Composite |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 2
ในฐานะที่คุณอาจสังเกตเห็นว่าคลาส "Composite" แต่ละคลาสไม่ได้อยู่ในลำดับชั้นที่แยกจากกันอีกต่อไป แต่ถูกรวมเข้าเป็นลำดับชั้นที่แชร์หรือแชร์ทั่วไป
จากนั้นให้เพิ่มสมาชิกที่เหมือนกันสามารถย้ายไปที่ซูเปอร์คลาสและสมาชิกที่แตกต่างกันไปยังคลาสพื้นฐานแต่ละคลาส
และอย่างที่คุณทราบแล้ววิธีการ "เสมือน" หรือ "โอเวอร์โหลด" ถูกกำหนดไว้ในคลาสฐาน แต่แทนที่ในคลาสย่อย เหมือนรูปที่ 3
................................................
.............+--------------------+.............
.............| Common:: |.............
.............| Composite |.............
.............+--------------------+.............
.............| [+] void AddChild()|.............
.............+---------+----------+.............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Composite |........| Composite |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 3
โปรดทราบว่าอาจมีบางคลาสที่ไม่มีสมาชิกและคุณอาจถูกล่อลวงให้ลบคลาสเหล่านั้นไม่ออก พวกเขาถูกเรียกว่า "ชั้นเรียนกลวง", "ชั้นเรียนแบบนับจำนวน" และชื่ออื่น ๆ
2 คลาสย่อย
ลองย้อนกลับไปที่แผนภาพแรก แต่ละคลาส "Composite" มีคลาสย่อย "Viewee" ในแต่ละลำดับชั้น
กระบวนการซ้ำสำหรับแต่ละชั้นเรียน หมายเหตุกว่ารูปที่ 4 คลาส "Common :: Viewee" สืบทอดมาจาก "Common :: Composite" แต่เพื่อความเรียบง่ายคลาส "Common :: Composite" จะถูกละเว้นจากแผนภาพ
................................................
.............+--------------------+.............
.............| Common:: |.............
.............| Viewee |.............
.............+--------------------+.............
.............| ... |.............
.............+---------+----------+.............
.......................|........................
.......................^........................
....................../.\.......................
.....................+-+-+......................
.......................|........................
..........+------------+------------+...........
..........|.........................|...........
..+-------+--------+........+-------+--------+..
..| Canvas:: |........| SVG:: |..
..| Viewee |........| Viewee |..
..+----------------+........+----------------+..
..| ... |........| ... |..
..+----------------+........+----------------+..
................................................
Figure 4
คุณจะสังเกตได้ว่า "Canvas :: Viewee" และ "SVG :: Viewee" ไม่ได้สืบทอดมาจาก "Composite" ที่เกี่ยวข้องอีกต่อไป แต่มาจาก Common "View :: Viewee ทั่วไป" แทน
คุณสามารถเพิ่มสมาชิกได้ทันที
......................................................
.........+------------------------------+.............
.........| Common:: |.............
.........| Viewee |.............
.........+------------------------------+.............
.........| [+] bool Validate() |.............
.........| [+] Rect GetAbsoluteBounds() |.............
.........+-------------+----------------+.............
.......................|..............................
.......................^..............................
....................../.\.............................
.....................+-+-+............................
.......................|..............................
..........+------------+----------------+.............
..........|.............................|.............
..+-------+---------+........+----------+----------+..
..| Canvas:: |........| SVG:: |..
..| Viewee |........| Viewee |..
..+-----------------+........+---------------------+..
..| |........| [+] Viewee Element |..
..+-----------------+........+---------------------+..
..| [+] void Paint()|........| [+] void addChild() |..
..+-----------------+........+---------------------+..
......................................................
Figure 5
3 ทำซ้ำกระบวนการ
กระบวนการจะดำเนินต่อไปสำหรับแต่ละคลาส "Canvas :: Visual" จะไม่สืบทอดจาก "Canvas :: Viewee" จาก "Commons :: Visual", "Canvas :: Structural" จะไม่สืบทอดมาจาก "Canvas :: Viewee ", buit จาก" Commons :: Structural "และอื่น ๆ
4 แผนภาพลำดับชั้น 3D
คุณจะได้รับการเรียงลำดับของไดอะแกรมสามมิติที่มีเลเยอร์หลายชั้นบนสุดมีลำดับชั้น "ทั่วไป" และชั้นล่างสุดมีลำดับชั้นเพิ่มเติมแต่ละอัน
ลำดับชั้นคลาสอิสระดั้งเดิมของคุณซึ่งมีลักษณะคล้ายกับนี้ (รูปที่ 6):
.................................................
..+-----------------+.......+-----------------+..
..| Common:: |.......| SVG:: |..
..| Composite |.......| Composite |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Viewee |.......| Viewee |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Visual |.......| Visual |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+--------+--------+..
...........|.........................|...........
...........^.........................^...........
........../.\......................./.\..........
.........+-+-+.....................+-+-+.........
...........|.........................|...........
..+--------+--------+.......+--------+--------+..
..| Common:: |.......| SVG:: |..
..| Rect |.......| Rect |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+-----------------+.......+-----------------+..
.................................................
Figure 6
โปรดทราบว่าบางคลาสจะถูกตัดออกและลำดับชั้น "Canvas" ทั้งหมดจะถูกตัดออกเพื่อให้ง่ายขึ้น
ลำดับชั้นของคลาสรวมขั้นสุดท้ายอาจเป็นสิ่งที่คล้ายกับสิ่งนี้:
.................................................
..+-----------------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Composite |...\+..| Composite |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Viewee |...\+..| Viewee |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Visual |...\+..| Visual |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+--------+--------+.......+-----------------+..
...........|.....................................
...........^.....................................
........../.\....................................
.........+-+-+...................................
...........|.....................................
..+--------+--------+.../+..+-----------------+..
..| Common:: +--<.+--+ SVG:: |..
..| Rect |...\+..| Rect |..
..+-----------------+.......+-----------------+..
..| ... |.......| ... |..
..+-----------------+.......+-----------------+..
.................................................
Figure 7
โปรดทราบว่าบางคลาสจะถูกละไว้และคลาส "Canvas" ทั้งหมดจะถูกตัดออกเพื่อให้ง่าย แต่จะคล้ายกับคลาส "SVG"
คลาส "Common" สามารถแสดงเป็นเลเยอร์เดียวของไดอะแกรม 3 มิติคลาส "SVG" ในอีกชั้นหนึ่งและคลาส "Canvas" ในเลเยอร์ที่สาม
ตรวจสอบว่าแต่ละเลเยอร์เกี่ยวข้องกับชั้นแรกซึ่งแต่ละชั้นมีคลาสพาเรนต์ของลำดับชั้น "ทั่วไป"
การติดตั้งโค้ดอาจต้องใช้อย่างใดอย่างหนึ่ง, การสืบทอดส่วนต่อประสาน, การสืบทอดคลาสหรือ "มิกซ์อิน" ขึ้นอยู่กับสิ่งที่ภาษาการเขียนโปรแกรมของคุณรองรับ
สรุป
ในฐานะที่เป็นโซลูชั่นการเขียนโปรแกรมใด ๆ อย่ารีบเร่งในการเพิ่มประสิทธิภาพการเพิ่มประสิทธิภาพเป็นสิ่งสำคัญมาก แต่การเพิ่มประสิทธิภาพที่ไม่ดีอาจกลายเป็นปัญหาใหญ่กว่าปัญหาเดิม
ฉันไม่แนะนำให้ใช้ "โซลูชัน 1" หรือ "โซลูชัน 2" อย่างใดอย่างหนึ่ง
ใน "โซลูชัน 1" ไม่ได้ใช้เนื่องจากต้องใช้การสืบทอดในแต่ละกรณี
"Solution 2", "Mixins" อาจถูกนำไปใช้ แต่หลังจากออกแบบคลาสและลำดับชั้น
Mixins เป็นทางเลือกสำหรับการสืบทอดตามอินเตอร์เฟสหรือการสืบทอดหลายคลาสที่อิงกับคลาส
โซลูชัน 3 ที่เสนอของฉันบางครั้งเรียกว่ารูปแบบการออกแบบ "ลำดับชั้นแบบขนาน" หรือรูปแบบการออกแบบ "ลำดับชั้นคู่"
นักพัฒนา / นักออกแบบหลายคนจะไม่เห็นด้วยกับมันและเชื่อว่ามันไม่ควรมีอยู่ แต่ฉันใช้ตัวเองผิดและนักพัฒนาอื่น ๆ เพื่อแก้ปัญหาทั่วไปเช่นคำถามของคุณ
อีกสิ่งที่ขาดหายไป ในการแก้ปัญหาก่อนหน้าของคุณปัญหาหลักไม่ได้เกิดขึ้นว่าจะใช้ "mixins" หรือ "interfaces" แต่เพื่อปรับแต่งก่อนรูปแบบของชั้นเรียนของคุณและใช้คุณลักษณะภาษาการเขียนโปรแกรมที่มีอยู่ในภายหลัง