ลำดับชั้นแบบขนาน - เหมือนกันบางส่วนแตกต่างกันเล็กน้อย


12

มีคำถามที่คล้ายกันอยู่สองสามข้อ 1 ,2 ,3 ,4แต่ดูเหมือนว่าไม่ใช่ในกรณีของคำถามนี้และการแก้ปัญหาก็ดูดีที่สุด

นี่เป็นคำถามทั่วไปของ OOP โดยสมมติว่ามีหลายรูปแบบชื่อสามัญและมิกซ์อินมีอยู่ ภาษาจริงที่ใช้คือ OOP Javascript (Typescript) แต่เป็นปัญหาเดียวกันใน Java หรือ C ++

ฉันมีลำดับชั้นของชั้นเรียนแบบขนานซึ่งบางครั้งก็มีพฤติกรรมที่เหมือนกัน (ส่วนต่อประสานและการใช้งาน) แต่บางครั้งก็มีพฤติกรรมที่ 'ได้รับการป้องกัน' ของตัวเอง ภาพประกอบดังนี้:

3 ลำดับชั้นของคลาสแบบขนานคอลัมน์กลางแสดงส่วนทั่วไปคอลัมน์ด้านซ้ายคือลำดับชั้นของผืนผ้าใบและคอลัมน์ด้านขวาแสดงลำดับชั้น SVG

นี้สำหรับวัตถุประสงค์ในการประกอบการอธิบายเท่านั้น ; มันไม่ใช่แผนภาพคลาสที่แท้จริง หากต้องการอ่าน:

  • สิ่งใดก็ตามในลำดับชั้นทั่วไป (กลาง) จะแชร์กันระหว่างทั้ง Canvas (ซ้าย) และ SVG (ขวา) ด้วยการแบ่งปันฉันหมายถึงทั้งอินเทอร์เฟซและการใช้งาน
  • สิ่งใดก็ตามที่อยู่บนคอลัมน์ซ้ายหรือขวาหมายถึงพฤติกรรม (วิธีการและสมาชิก) เฉพาะสำหรับลำดับชั้นนั้น ตัวอย่างเช่น:
    • ทั้งลำดับชั้นซ้ายและขวาใช้กลไกการตรวจสอบความถูกต้องเดียวกันแสดงเป็นวิธีการเดียว ( Viewee.validate()) ในลำดับชั้นทั่วไป
    • paint()เพียงลำดับชั้นของผ้าใบมีวิธีการ วิธีนี้เรียกวิธีการทาสีบนเด็กทุกคน
    • ลำดับชั้น SVG จำเป็นต้องแทนที่addChild()วิธีการCompositeแต่ไม่ได้เป็นกรณีที่มีลำดับชั้นของผืนผ้าใบ
  • โครงสร้างจากลำดับชั้นทั้งสองไม่สามารถผสมกันได้ โรงงานทำให้มั่นใจได้ว่า

โซลูชัน I - Tease Apart Inheritance

Tease Apart Inheritance ของ Fowler ดูเหมือนจะไม่ทำงานที่นี่เพราะมีความคลาดเคลื่อนระหว่างสองแนว

โซลูชัน II - มิกซ์อิน

นี่เป็นสิ่งเดียวที่ฉันสามารถนึกได้ ทั้งสองลำดับชั้นมีการพัฒนาแยกจากกัน แต่ในแต่ละระดับชั้นเรียนผสมในชั้นเรียนทั่วไปซึ่งไม่ได้เป็นส่วนหนึ่งของลำดับชั้นของชั้นเรียน ไม่ใช้structuralส้อมจะมีลักษณะดังนี้:

คอลัมน์สามคอลัมน์อีกครั้งคอลัมน์ด้านซ้ายและขวาเป็นลำดับชั้นแบบขนานโดยที่แต่ละคลาสนั้นมีอยู่ในคลาสทั่วไปด้วย  คลาสทั่วไปไม่ได้เป็นส่วนหนึ่งของลำดับชั้น

โปรดทราบว่าแต่ละคอลัมน์จะอยู่ในเนมสเปซของตนเองดังนั้นชื่อคลาสจะไม่ขัดแย้งกัน

คำถาม

ทุกคนสามารถเห็นข้อบกพร่องด้วยวิธีนี้ได้หรือไม่? ทุกคนคิดวิธีที่ดีกว่าได้ไหม


ภาคผนวก

นี่คือตัวอย่างโค้ดที่จะใช้ เนมสเปซsvgอาจถูกแทนที่ด้วยcanvas:

var iView        = document.getElementById( 'view' ),
    iKandinsky   = new svg.Kandinsky(),
    iEpigone     = new svg.Epigone(),
    iTonyBlair   = new svg.TonyBlair( iView, iKandinsky ),
    iLayer       = new svg.Layer(),
    iZoomer      = new svg.Zoomer(),
    iFace        = new svg.Rectangle( new Rect( 20, 20, 100, 60) ),
    iEyeL        = new svg.Rectangle( new Rect( 20, 20, 20, 20) ),
    iEyeR        = new svg.Rectangle( new Rect( 60, 20, 20, 20) );

iKandinsky.setContext( iTonyBlair.canvas.getContext( '2d' ) );
iEpigone.setContext( iTonyBlair.canvas.getContext( '2d' ) );

iFace.addChildren( iEyeL, iEyeR );
iZoomer.setZoom( new Point( 2, 2 ) );
iZoomer.addChild( iFace );
iLayer.addChild( iZoomer );
iTonyBlair.setContent( iLayer );

โดยพื้นฐานแล้วในไคลเอนต์รันไทม์ประกอบด้วยลำดับชั้นอินสแตนซ์ของคลาสย่อยของ Viewee ชอบมาก:

รูปภาพแสดงลำดับชั้นของวัตถุเช่นเลเยอร์, ​​rect, scroller เป็นต้น

สมมติว่าผู้ชมเหล่านี้ทั้งหมดมาจากลำดับชั้นของภาพวาดพวกเขาจะแสดงผลโดยการข้ามผ่านลำดับชั้นที่สามารถเรียกดูได้paint()ในแต่ละวิว หากมาจากลำดับชั้น svg ผู้ดูจะรู้วิธีเพิ่มตัวเองใน DOM แต่ไม่มีการpaint()แวะผ่าน



อาจลองใช้รูปแบบการออกแบบมัณฑนากรเต็มรูปแบบ (Erich Gamma et als, Design Patterns)
Zon

ผู้ชมคืออะไร "ขนาน" หมายถึงคำนามอะไร (ตรงข้ามกับคำคุณศัพท์)?
Tulains Córdova

คุณมีหลายมรดกหรือไม่
Tulains Córdova

คลาส Canvas หรือ SVG มีสถานะหรือข้อมูลเพิ่มเติมที่ไม่เหมือนกันหรือไม่? คุณใช้คลาสอย่างไร คุณสามารถแสดงรหัสตัวอย่างบางส่วนที่แสดงว่า hiearchies เหล่านี้สามารถใช้งานได้อย่างไร
ร่าเริง

คำตอบ:


5

วิธีที่สองแยกอินเตอร์เฟสที่ดีกว่าตามหลักการแยกอินเตอร์เฟส

อย่างไรก็ตามฉันจะเพิ่มส่วนต่อประสาน Paintable

ฉันจะเปลี่ยนชื่อด้วย ไม่จำเป็นต้องสร้างความสับสน:

// common

public interface IComposite {
    public void addChild(Composite e);
}

public interface IViewee extends IComposite{
    public void validate();
    public List<IBound> getAbsoluteBouns();
}

public interface IVisual {
    public List<IBound> getBounds();
}

public interface IRec {
}

public interface IPaintable {
    public void paint();
}

// canvas

public interface ICanvasViewee extends IViewee, IPaintable {
}

public interface ICanvasVisual extends IViewee, IVisual {
}

public interface ICanvasRect extends ICanvasVisual, IRec {
}


// SVG

public interface ISVGViewee extends IViewee {
    public void element();
}

public interface ISVGVisual extends IVisual, ISVGViewee {
}

public interface ISVGRect extends ISVGVisual, IRect {
}

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

ไม่ downvoter แต่อินเตอร์เฟซ IMHO ชี้แจงไม่ได้เป็นรูปแบบที่ดี
dagnelies

@arnaud คุณหมายถึงอะไร "อินเตอร์เฟซเอ็กซ์โปเนนเชียล"
Tulains Córdova

@ user61852 ... เอาล่ะสมมติว่ามันมีอินเตอร์เฟสมากมาย "exponential" เป็นคำที่ผิดจริง ๆ มันเหมือนกับ "multiplicative" ในแง่ที่ว่าถ้าคุณมี "facets" (คอมโพสิต, ภาพ, ทาสีได้ ... ) และ "องค์ประกอบ" เพิ่มเติม (canvas, svg ... ) คุณจะต้องจบลงด้วยอินเตอร์เฟสมากมาย
dagnelies

@arnaud คุณมีประเด็น แต่อย่างน้อยก็มีการออกแบบที่ยืดหยุ่นล่วงหน้าและฝันร้ายที่สืบทอดมาจาก OP จะแก้ไขได้เมื่อคุณไม่รู้สึกว่าถูกบังคับให้ต้องขยายเวลา คุณขยายคลาสบางคลาสถ้าคุณต้องการและไม่ถูกบังคับโดยลำดับชั้นที่วางแผนไว้
Tulains Córdova

3

นี่เป็นคำถามทั่วไปของ OOP โดยสมมติว่ามีหลายรูปแบบชื่อสามัญและมิกซ์อินมีอยู่ ภาษาจริงที่ใช้คือ OOP Javascript (Typescript) แต่เป็นปัญหาเดียวกันใน Java หรือ C ++

ที่จริงไม่เป็นความจริงเลย typescript มีข้อได้เปรียบที่สำคัญกว่า Java - กล่าวคือการพิมพ์โครงสร้าง คุณสามารถทำสิ่งที่คล้ายกันใน C ++ ด้วยเทมเพลตที่พิมพ์เป็ด แต่มันเป็นความพยายามมากขึ้น

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

สิ่งนี้ทำให้คุณเป็นอิสระจากความต้องการในการกำหนดลำดับชั้นของอินเทอร์เฟซและกำหนดว่าคลาสใดควรขยายอินเทอร์เฟซใด

เพียงแค่กำหนดแต่ละคลาสและลืมเกี่ยวกับการพิมพ์โครงสร้างอินเตอร์เฟสจะดูแล

ตัวอย่างเช่น:

class SVGViewee {
    validate() { /* stuff */ }
    addChild(svg: SVG) { /* stuff */ }
}
class CanvasViewee {
    validate() { /* stuff */ }
    paint() { /* stuff */ }
}
interface SVG {
    addChild: { (svg: SVG): void };
}
f(viewee: { validate: { (): boolean }; }) {
    viewee.validate();
}
g(svg: SVG) {
    svg.addChild(svg);
}
h(canvas: { paint: { (): void }; }) {
    canvas.paint();
}
f(SVGViewee());
f(CanvasViewee());
g(SVGViewee());
h(CanvasViewee());

นี่คือ typescript ที่ถูกต้องตามกฎหมายโดยสิ้นเชิง ขอให้สังเกตว่าฟังก์ชั่นการบริโภคไม่ทราบหรือให้อึเพียงครั้งเดียวเกี่ยวกับคลาสพื้นฐานหรืออินเทอร์เฟซที่ใช้ในคำจำกัดความของคลาส

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


ดูเหมือนว่าจะมีแนวโน้ม แต่ฉันไม่เข้าใจข้อเสนอจริง ๆ (ขออภัยอาจมีอคติ OOP มากเกินไป) บางทีคุณสามารถแบ่งปันตัวอย่างรหัสได้ไหม? ตัวอย่างเช่นทั้งsvg.Vieweeและcanvas.Vieweeต้องการvalidate()วิธี (การใช้งานซึ่งเหมือนกันทั้งคู่); ดังนั้นsvg.Vieweeเพียงอย่างเดียวจึงต้องแทนที่addChild ()ในขณะที่เฉพาะcanvas.Vieweeต้องการโปรแกรมระบายสี () (ซึ่งเรียกใช้โปรแกรมระบายสี ()สำหรับเด็กทุกคน - ซึ่งเป็นสมาชิกของคลาสคอมโพสิตฐาน) ดังนั้นฉันจึงไม่สามารถมองเห็นสิ่งนี้ด้วยการพิมพ์เชิงโครงสร้าง
Izhaki

คุณกำลังพิจารณาทุกสิ่งที่ไม่สำคัญในกรณีนี้
DeadMG

ดังนั้นฉันอาจไม่ได้รับคำตอบเลย คงจะดีถ้าคุณทำอย่างละเอียด
Izhaki

ฉันแก้ไข บรรทัดล่างคือว่าคลาสพื้นฐานนั้นไม่เกี่ยวข้องอย่างแน่นอนและไม่มีใครใส่ใจเกี่ยวกับพวกเขา พวกเขามีรายละเอียดการใช้งานเท่านั้น
DeadMG

1
ตกลง. นี่เป็นการเริ่มต้นที่สมเหตุสมผล A) ฉันรู้ว่าการพิมพ์เป็ดคืออะไร B) ฉันไม่แน่ใจว่าเพราะเหตุใดอินเทอร์เฟซจึงเป็นศูนย์กลางในคำตอบนี้ - การแบ่งคลาสเพื่อประโยชน์ในการแบ่งปันพฤติกรรมทั่วไปคุณสามารถละเว้นอินเทอร์เฟซได้อย่างปลอดภัยในตอนนี้ C) พูดในตัวอย่างที่คุณมีSVGViewee.addChild()แต่CanvasVieweeต้องการคุณสมบัติเดียวกันทั้งหมด ดูเหมือนว่าจะสมเหตุสมผลสำหรับฉันว่าทั้งคู่มาจากคอมโพสิต?
Izhaki

3

ภาพรวมอย่างรวดเร็ว

โซลูชันที่ 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" แต่เพื่อปรับแต่งก่อนรูปแบบของชั้นเรียนของคุณและใช้คุณลักษณะภาษาการเขียนโปรแกรมที่มีอยู่ในภายหลัง


ขอบคุณสำหรับคำตอบอย่างละเอียด ผมคิดว่าผมเข้าใจว่ามันไม่เป็นไรเพื่อให้ฉันถามนี้และทุกลูกหลานต้องมีวิธีการที่เรียกว่าcanvas.viewee paint()ทั้งcommonหรือsvgเรียนจำเป็นต้องใช้มัน แต่ในโซลูชันของคุณมีลำดับชั้นcommonไม่เหมือนcanvasหรือsvgเหมือนในโซลูชันของฉัน 2 ดังนั้นpaint()จะสิ้นสุดลงอย่างไรในคลาสย่อยทั้งหมดcanvas.vieweeหากไม่มีการสืบทอด
Izhaki

@Izhaki ขออภัยหากมีข้อบกพร่องเล็กน้อยในคำตอบของฉัน แล้วpaint()ควรจะย้ายหรือประกาศใน "ผ้าใบ :: viewee" แนวคิดรูปแบบทั่วไปยังคงอยู่ แต่สมาชิกบางคนอาจต้องย้ายหรือเปลี่ยนแปลง
umlcat

ตกลงดังนั้นวิธีการที่ไม่ย่อยได้รับมันถ้าไม่มีใครมาจากจากcanvas::viewee?
Izhaki

คุณใช้เครื่องมือในการสร้างงานศิลปะ ASCII ของคุณหรือไม่? (ฉันไม่แน่ใจว่าจุดช่วยจริงสำหรับสิ่งที่คุ้มค่า)
Aaron Hall

1

ในบทความเรื่องรูปแบบการออกแบบสำหรับการซื้อขายกับคู่มรดกลำดับชั้นใน C ++ , ลุงบ๊อบนำเสนอวิธีการแก้ปัญหาที่เรียกว่าStairway to Heaven มันระบุไว้เจตนา:

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

และแผนภาพให้:

แผนผังคลาสที่มีโครงสร้างการสืบทอดสองขนานซึ่งแต่ละคลาสทางด้านขวานั้นมีอยู่ในคลาสเดียวกันทางด้านซ้าย  ลำดับชั้นด้านซ้ายยังยึดตามการสืบทอดเสมือนอย่างสมบูรณ์

แม้ว่าในโซลูชันที่ 2 จะไม่มีการสืบทอดเสมือนจริง แต่เป็นไปตามรูปแบบของStairway to Heaven ดังนั้นวิธีที่ 2 ดูเหมือนจะสมเหตุสมผลกับปัญหานี้

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