มรดกเทียบกับองค์ประกอบสำหรับชิ้นหมากรุก


9

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

การสืบทอดจะมีลักษณะเช่นนี้ (พร้อมตัวสร้างที่เหมาะสม ฯลฯ )

class BasePiece
{
    virtual Squares GetValidMoveSquares() = 0;
    Mesh* mesh;
    // Other fields
}

class Pawn : public BasePiece
{
   Squares GetValidMoveSquares() override;
}

ซึ่งแน่นอนว่าเป็นไปตามหลักการ "เป็น -a" ในขณะที่องค์ประกอบจะมีลักษณะเช่นนี้

class MovementComponent
{
    virtual Squares GetValidMoveSquares() = 0;
}

class PawnMovementComponent
{
     Squares GetValidMoveSquares() override;
}

enum class Type
{
     PAWN,
     BISHOP, //etc
}


class Piece
{
    MovementComponent* movementComponent;
    MeshComponent* mesh;
    Type type;
    // Other fields
 }

มันเป็นเรื่องของการตั้งค่าส่วนตัวหรือเป็นวิธีหนึ่งที่ชัดเจนกว่าทางเลือกอื่นที่นี่หรือไม่

แก้ไข: ฉันคิดว่าฉันเรียนรู้บางสิ่งจากคำตอบทุกข้อดังนั้นฉันจึงรู้สึกไม่ดีที่เลือกเพียงหนึ่งข้อ ทางออกสุดท้ายของฉันจะได้รับแรงบันดาลใจจากโพสต์ต่างๆที่นี่ (ยังทำงานอยู่) ขอบคุณทุกคนที่สละเวลาตอบ


ฉันเชื่อว่าทั้งสองสามารถมีอยู่เคียงข้างกันทั้งสองนี้มีจุดประสงค์ที่แตกต่างกัน แต่สิ่งเหล่านี้ไม่ได้แยกจากกัน .. หมากรุกประกอบด้วยชิ้นส่วนและกระดานที่แตกต่างกันและชิ้นส่วนต่างกัน ชิ้นส่วนเหล่านี้แบ่งปันคุณสมบัติและพฤติกรรมพื้นฐานบางอย่างและยังมีคุณสมบัติและพฤติกรรมที่เฉพาะเจาะจง ดังนั้นตามที่ฉันควรจะใช้องค์ประกอบบนกระดานและชิ้นส่วนในขณะที่ควรได้รับมรดกตามประเภทของชิ้นส่วน
Hitesh Gaur

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

รูปแบบกลยุทธ์เป็นเรื่องธรรมดาในการเขียนโปรแกรมเกมด้วยเหตุผล var Pawn = new Piece(howIMove, howITake, whatILookLike)ดูเหมือนง่ายกว่าฉันจัดการและดูแลรักษาได้ง่ายกว่าลำดับชั้นการสืบทอด
Ant P

@AntP นั่นเป็นจุดที่ดีขอบคุณ!
CanISleepYet

@AntP ให้คำตอบ! ... มันมีข้อดีอย่างมาก!
svidgen

คำตอบ:


4

ได้อย่างรวดเร็วก่อนคำตอบของคุณอ้างว่า "การแต่งเพลง" ไม่ได้ใช้มรดก แต่ฉันเดาว่าคุณแค่ลืมเพิ่ม:

class PawnMovementComponent : MovementComponent
{
     Squares GetValidMoveSquares() override;
}

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

น่าเสียดายที่โซลูชันนี้มีข้อบกพร่อง: Pieceขณะนี้แต่ละข้อมูลเก็บไว้เป็นข้อมูลประเภทซ้ำซ้อนสองครั้ง:

  • ภายในตัวแปรสมาชิก type

  • ภายในmovementComponent(พิมพ์ซ้ำโดยกลุ่มย่อย)

ความซ้ำซ้อนนี้เป็นสิ่งที่สามารถนำคุณเข้าสู่ปัญหาได้ - คลาสแบบง่าย ๆ เช่นPieceควรให้ "แหล่งความจริงเดียว" ไม่ใช่แหล่งที่มาสองแห่ง

แน่นอนคุณสามารถลองจัดเก็บข้อมูลประเภทเฉพาะในtypeและสร้างไม่มีคลาสย่อยMovementComponentเช่นกัน แต่การออกแบบนี้ส่วนใหญ่อาจจะนำไปสู่ใหญ่ " switch(type)" GetValidMoveSquaresคำสั่งในการดำเนินการ และที่แน่นอนเป็นตัวบ่งชี้ที่แข็งแกร่งสำหรับการรับมรดกเป็นทางเลือกที่ดีที่นี่

หมายเหตุใน "มรดก" การออกแบบมันเป็นเรื่องง่ายมากที่จะให้ช่อง "ประเภท" ในทางที่ไม่ซ้ำซ้อน: เพิ่มวิธีการเสมือนGetType()การBasePieceและดำเนินการได้ตามในแต่ละชั้นฐาน

เกี่ยวกับ "การส่งเสริม": ฉันอยู่ที่นี่ด้วย @svidgen ฉันพบข้อโต้แย้งที่แสดงในคำตอบ @ @CatWhisperer ของที่ถกเถียงกัน

การตีความ "การโปรโมต" เป็นการแลกเปลี่ยนทางกายภาพของชิ้นแทนที่จะตีความว่าเป็นการเปลี่ยนประเภทของชิ้นส่วนเดียวกันให้ความรู้สึกเป็นธรรมชาติมากกว่าสำหรับฉัน ดังนั้นการใช้สิ่งนี้ในลักษณะที่คล้ายกัน - โดยการแลกเปลี่ยนชิ้นส่วนหนึ่งโดยอีกประเภทหนึ่ง - อาจจะไม่ทำให้เกิดปัญหาใหญ่ - อย่างน้อยก็ไม่ใช่สำหรับกรณีเฉพาะของหมากรุก


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

@CanISleepYet: ปัญหากับการเสนอช่อง "ประเภท" movementComponentของคุณจะถูกก็อาจแตกต่างจากชนิดย่อยของ ดูการแก้ไขวิธีการระบุเขตข้อมูลชนิดของฉันอย่างปลอดภัยในการออกแบบ "การสืบทอด"
Doc Brown

4

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

ตัวเลือกการสืบทอดนั้นมีรหัสน้อยกว่าและมีความซับซ้อนน้อยกว่า ชิ้นส่วนแต่ละประเภทมีความสัมพันธ์แบบ "ไม่เปลี่ยนรูปแบบ" 1 ต่อ 1 กับลักษณะการเคลื่อนไหว (ซึ่งแตกต่างจากการเป็นตัวแทนซึ่งเป็น 1 ต่อ 1 แต่ไม่จำเป็นต้องเปลี่ยนไม่ได้ - คุณอาจต้องการเสนอ "สกิน" ที่หลากหลาย)

หากคุณแบ่งความสัมพันธ์แบบ 1 ต่อ 1 ที่ไม่เปลี่ยนรูปแบบระหว่างชิ้นส่วนและพฤติกรรม / การเคลื่อนไหวของพวกเขาออกเป็นหลาย ๆ คลาสคุณอาจแค่เพิ่มความซับซ้อนเท่านั้นและไม่มาก ดังนั้นหากฉันกำลังตรวจสอบหรือรับรหัสนั้นฉันคาดว่าจะเห็นเหตุผลที่ดีและเป็นเอกสารสำหรับความซับซ้อน

ทั้งหมดที่กล่าวว่าเป็นตัวเลือกได้ง่าย , IMO คือการสร้างPiece อินเตอร์เฟซที่แต่ละชิ้นของคุณใช้ ส่วนภาษานี้เป็นจริงมากแตกต่างจากการรับมรดกเพราะอินเตอร์เฟซจะไม่ จำกัด คุณจากการใช้อินเตอร์เฟซที่อื่น ... คุณเพียง แต่ไม่ได้รับพฤติกรรมแบบคลาสเบสฟรีในกรณีนี้: คุณต้องการเปลี่ยนพฤติกรรมแบบใช้ร่วมกันที่อื่น


ฉันไม่ซื้อว่าโซลูชันการสืบทอดคือ 'โค้ดน้อยกว่าบรรทัด' บางทีในชั้นนี้ แต่ไม่รวม
JimmyJames

@JimmyJames จริงเหรอ? ... เพียงนับจำนวนบรรทัดของรหัสใน OP ... ยอมรับว่าไม่ใช่โซลูชันทั้งหมด แต่ไม่ใช่ตัวบ่งชี้ที่ไม่ดีซึ่งโซลูชันนี้ใช้ LOC และความซับซ้อนมากขึ้นในการรักษา
svidgen

ฉันไม่ต้องการที่จะปรับจุดนี้ให้ดีขึ้นเพราะมันเกี่ยวกับจุดนี้ แต่ใช่ฉันคิดอย่างนั้น การช่วงชิงของฉันเป็นที่ของรหัสนี้เล็กน้อยเมื่อเทียบกับโปรแกรมทั้งหมด หากสิ่งนี้ทำให้การใช้กฎง่ายขึ้น (เป็นที่ถกเถียงกัน) คุณอาจบันทึกรหัสได้หลายสิบหรือหลายร้อยบรรทัด
JimmyJames

ขอบคุณฉันไม่ได้คิดถึงอินเทอร์เฟซ แต่คุณอาจพูดถูกว่านี่เป็นวิธีที่ดีที่สุด เรียบง่ายขึ้นเกือบดีกว่าเสมอ
CanISleepYet

2

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

ในโลกธุรกิจอย่างไรก็ตามไม่มีการกำหนดอย่างเคร่งครัดเช่นนี้ - กฎเกณฑ์ทางธุรกิจและความต้องการเปลี่ยนแปลงไปตามกาลเวลาและโปรแกรมต้องเปลี่ยนแปลงตลอดเวลาเพื่อรองรับ นี่คือที่ที่ - กับ vs. มี - ข้อมูลสร้างความแตกต่าง ที่นี่ความเรียบง่ายทำให้การแก้ปัญหาที่ซับซ้อนง่ายขึ้นเพื่อรักษาเมื่อเวลาผ่านไปและความต้องการที่เปลี่ยนแปลง โดยทั่วไปในทางธุรกิจเราต้องจัดการกับความเพียรซึ่งอาจเกี่ยวข้องกับฐานข้อมูลเช่นกัน ดังนั้นเราจึงมีกฎที่ไม่ต้องใช้หลายคลาสเมื่อคลาสเดียวจะทำงานและไม่ใช้การสืบทอดเมื่อมีการจัดองค์ประกอบที่เพียงพอ แต่กฎเหล่านี้ล้วน แต่มุ่งสู่การทำให้รหัสสามารถคงไว้ได้ในระยะยาวเมื่อเผชิญกับการเปลี่ยนแปลงกฎและข้อกำหนด - ซึ่งไม่ใช่กรณีของหมากรุก

ด้วยหมากรุกเส้นทางการบำรุงรักษาที่มีโอกาสมากที่สุดในระยะยาวคือโปรแกรมของคุณจำเป็นต้องฉลาดขึ้นและชาญฉลาดขึ้นซึ่งในที่สุดก็หมายถึงการเพิ่มประสิทธิภาพความเร็วและพื้นที่จัดเก็บ โดยทั่วไปแล้วคุณจะต้องแลกเปลี่ยนสิ่งที่เสียสละเพื่อให้สามารถอ่านได้เพื่อประสิทธิภาพและแม้แต่การออกแบบ OO ที่ดีที่สุดก็จะไปตามทาง


โปรดทราบว่ามีเกมที่ประสบความสำเร็จมากมายที่นำแนวคิดและจากนั้นนำสิ่งใหม่ ๆ มาผสม หากคุณอาจต้องการทำสิ่งนี้ในอนาคตด้วยเกมหมากรุกของคุณคุณควรคำนึงถึงการเปลี่ยนแปลงที่อาจเกิดขึ้นในอนาคต
Flater

2

ฉันจะเริ่มด้วยการสังเกตเกี่ยวกับโดเมนปัญหา (เช่นกฎของหมากรุก):

  • ชุดของการเคลื่อนไหวที่ถูกต้องสำหรับชิ้นส่วนนั้นไม่ได้ขึ้นอยู่กับชนิดของชิ้นส่วนเท่านั้น แต่สถานะของกระดาน (การจำนำสามารถเคลื่อนที่ไปข้างหน้าได้ถ้าช่องว่าง / สามารถเคลื่อนที่ในแนวทแยงถ้าจับชิ้น)
  • การกระทำบางอย่างเกี่ยวข้องกับการนำชิ้นส่วนที่มีอยู่ออกจากการเล่น (การเลื่อนตำแหน่ง / การจับชิ้นส่วน) หรือการย้ายหลายชิ้น (การหล่อ)

สิ่งเหล่านี้น่าอึดอัดใจกับแบบจำลองที่เป็นความรับผิดชอบของตัวมันเองและการสืบทอดและการแต่งเพลงไม่ได้ให้ความรู้สึกที่ดีที่นี่ มันจะเป็นเรื่องธรรมดากว่าที่จะสร้างแบบจำลองกฎเหล่านี้ในฐานะพลเมืองชั้นหนึ่ง:

// pseudo-code, not pure C++

interface MovementRule {
  set<Square> getValidMoves(Board board, Square from); // what moves can I make from the given square?
  void makeMove(Board board, Square from, Square to); // update board state to reflect a specific move
}

class Game {
  Board board;
  map<PieceType, MovementRule> rules;
}

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


วิธีการที่น่าสนใจ - อาหารที่ดีสำหรับความคิด
CanISleepYet

1

ฉันคิดว่าในกรณีนี้การสืบทอดจะเป็นตัวเลือกที่สะอาดกว่า องค์ประกอบอาจจะดูสง่างามกว่านี้นิดหน่อย แต่ดูเหมือนว่าฉันจะถูกบังคับมากกว่านี้เล็กน้อย

หากคุณวางแผนที่จะพัฒนาเกมอื่นที่ใช้ชิ้นส่วนเคลื่อนไหวที่มีพฤติกรรมแตกต่างกันการจัดองค์ประกอบอาจเป็นตัวเลือกที่ดีกว่าโดยเฉพาะถ้าคุณใช้รูปแบบโรงงานเพื่อสร้างชิ้นส่วนที่จำเป็นสำหรับแต่ละเกม


2
คุณจะจัดการกับโปรโมชั่นโดยใช้การสืบทอดได้อย่างไร
TheCatWhisperer

4
@TheCatWhisperer คุณจัดการกับมันอย่างไรเมื่อคุณเล่นเกมทางกายภาพ? (หวังว่าคุณจะเปลี่ยนชิ้นส่วน - คุณไม่ได้แกะสลักตัวจำนำอีกแล้วใช่ไหม!?)
svidgen

0

ซึ่งแน่นอนเชื่อฟังหลักการ "เป็น -"

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


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

0

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

การเลื่อนตำแหน่งเมื่อผู้จำนำได้รับการดัดแปลงให้มีค่ามากขึ้นอาจเป็นปัญหาเกี่ยวกับการสืบทอด ในทางเทคนิคคุณสามารถจัดการกับสิ่งนี้ได้โดยการแทนที่ชิ้นส่วนหนึ่งด้วยอีกชิ้นหนึ่ง แต่วิธีนี้มีข้อ จำกัด หนึ่งในข้อ จำกัด เหล่านี้คือการติดตามสถิติชิ้นต่อชิ้นซึ่งคุณอาจไม่ต้องการรีเซ็ตข้อมูลชิ้นเมื่อโปรโมชั่น (หรือเขียนรหัสพิเศษเพื่อคัดลอกพวกเขาไป)

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

ฉันจะกำหนดPieceคลาส (ตามที่คุณมี) และPieceTypeคลาส PieceTypeระดับกำหนดวิธีการทั้งหมดที่จำนำ, Queen, ect ต้องกำหนดเช่นCanMoveTo, GetPieceTypeName, ect จากนั้นPawnและQueenคลาส ect จะได้รับมรดกจากPieceTypeคลาสอย่างแท้จริง


3
ปัญหาที่คุณเห็นด้วยการส่งเสริมการขายและการเปลี่ยนเป็นเรื่องเล็กน้อย IMO แยกของความกังวลเอกสารที่สวยมากว่าเช่น "ต่อการติดตามชิ้น" (หรืออะไรก็ตาม) ได้รับการจัดการอย่างเป็นอิสระอยู่แล้ว ... ข้อได้เปรียบที่เป็นไปได้ใด ๆ ที่โซลูชันของคุณเสนอนั้นถูกบดบังด้วยความกังวลในจินตนาการที่คุณกำลังพยายามจะกล่าวถึง IMO
svidgen

5
เพื่อชี้แจง: มีข้อดีบางอย่างสำหรับโซลูชันที่คุณเสนอ แต่มันก็ยากที่จะหาคำตอบของคุณซึ่งเน้นไปที่ปัญหาที่แก้ได้ง่ายใน "การถ่ายทอดทางพันธุกรรม" ... มันเป็นการเบี่ยงเบน (สำหรับฉัน) จากสิ่งที่คุณพยายามสื่อสารเกี่ยวกับความคิดเห็นของคุณ
svidgen

1
ถ้าPieceไม่ใช่เสมือนฉันเห็นด้วยกับวิธีนี้ ในขณะที่การออกแบบชั้นเรียนอาจดูซับซ้อนเล็กน้อยบนพื้นผิว แต่ฉันคิดว่าการใช้งานจะง่ายขึ้นโดยรวม สิ่งสำคัญที่จะเกี่ยวข้องกับPieceและไม่ใช่PieceTypeตัวตนและประวัติของการย้าย
JimmyJames

1
@svidgen การใช้งานที่ใช้ชิ้นส่วนที่ประกอบขึ้นมาและการใช้งานที่ใช้ชิ้นส่วนมรดกจะมีลักษณะเหมือนกันนอกเหนือจากรายละเอียดที่อธิบายไว้ในการแก้ปัญหานี้ วิธีการแก้ปัญหาการแต่งนี้จะเพิ่มทางอ้อมในระดับเดียว ฉันไม่เห็นว่าเป็นสิ่งที่ควรหลีกเลี่ยง
JimmyJames

2
@JimmyJames ถูกต้อง แต่ต้องมีการติดตามและย้ายประวัติของชิ้นงานหลายชิ้นซึ่งไม่ใช่ชิ้นส่วนใดที่ควรรับผิดชอบ IMO มันเป็น "ความกังวลแยกต่างหาก" ถ้าคุณเป็นคนประเภทต่าง ๆ
svidgen

0

จากมุมมองของฉันด้วยข้อมูลที่ให้ไว้ก็ไม่ควรตอบว่ามรดกหรือองค์ประกอบควรเป็นวิธีที่จะไปหรือไม่

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

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

นอกจากนี้ในการออกแบบที่สองของคุณความจริงที่ว่าPieceชั้นเรียนของคุณมีtypeสนามแสดงให้เห็นอย่างชัดเจนว่ามีปัญหาการออกแบบที่นี่เนื่องจากชิ้นส่วนของตัวเองอาจมีหลายประเภท มันฟังดูไม่น่าจะเป็นไปได้ที่จะใช้การสืบทอดบางอย่างซึ่งชิ้นส่วนนั้นเป็นของตัวเอง?

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

ต้องใช้ประสบการณ์บ้างในการใช้การสืบทอดและการจัดวางอย่างถูกต้อง แต่เป็นเครื่องมือที่แตกต่างกันโดยสิ้นเชิงและฉันไม่เชื่อว่าจะมีใครสามารถ "แทนที่" สิ่งหนึ่งด้วยอีกแบบหนึ่งได้แม้ว่าฉันจะเห็นด้วยว่าระบบนั้น


คุณสร้างจุดที่ดีว่าเป็นรุ่นที่สำคัญและไม่ใช่เครื่องมือ การรับมรดกซ้ำซ้อนช่วยได้จริงหรือ ตัวอย่างเช่นถ้าฉันต้องการเน้นการจำนำทั้งหมดหรือตรวจสอบว่าชิ้นส่วนเป็นราชาแล้วฉันจะไม่ต้องคัดเลือกนักแสดงหรือไม่?
CanISleepYet

-1

ฉันไม่แนะนำเลย

ในขณะที่การวางแนววัตถุเป็นเครื่องมือที่ดีและมักจะช่วยให้สิ่งต่าง ๆ ง่ายขึ้นมันไม่ได้เป็นเพียงเครื่องมือเดียวใน toolshed

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

ใช้ MSB สำหรับเจ้าของปล่อยให้ 7 บิตสำหรับชิ้นแม้ว่าสำรองศูนย์ว่างเปล่า
อีกทางหนึ่งคือศูนย์ว่างให้เซ็นชื่อให้เจ้าของค่าสัมบูรณ์สำหรับชิ้นงาน

หากคุณต้องการคุณสามารถใช้ bitfields เพื่อหลีกเลี่ยงการปิดบังด้วยตนเองถึงแม้ว่ามันจะไม่สามารถถอดได้:

class field {
    signed char data = 0;
public:
    constexpr field() = default;
    constexpr field(bool black, piece x) noexcept
    : data(x < piece::pawn || x > piece::king ? 0 : (black << 7) | x))
    {}
    constexpr bool is_black() noexcept { return data < 0; }
    constexpr bool is_white() noexcept { return data > 0; }
    constexpr bool empty() noexcept { return data == 0; }
    constexpr piece piece() noexcept { return piece(data & 0x7f); }
};

ที่น่าสนใจ ... และฉลาดพิจารณามันเป็น C ++ คำถาม แต่ไม่ใช่โปรแกรมเมอร์ซีพลัสพลัสนี่ไม่ใช่สัญชาตญาณแรกของฉัน (หรือสองหรือสาม )! ... นี่อาจเป็นคำตอบ C ++ ที่ดีที่สุดที่นี่!
svidgen

7
นี่คือ microoptimization ที่ไม่ควรมีการใช้งานจริง
โกหกที่

@LieRyan หากสิ่งที่คุณมีคือ OOP ทุกสิ่งจะมีกลิ่นเหมือนวัตถุ และไม่ว่าจะเป็น "micro" ก็เป็นคำถามที่น่าสนใจเช่นกัน ขึ้นอยู่กับว่าคุณทำอะไรกับมัน
Deduplicator

อืม ... ที่กล่าวว่า C ++ เป็นเชิงวัตถุ ผมถือว่ามีเหตุผล OP จะใช้ C ++ แทนที่จะเป็นเพียงแค่ C
svidgen

3
ที่นี่ฉันมีความกังวลน้อยลงเกี่ยวกับการขาด OOP แต่ค่อนข้างสับสนกับรหัสที่มีการกระตุกเล็กน้อย ยกเว้นว่าคุณกำลังเขียนโค้ดสำหรับ Nintendo 8 บิตหรือคุณกำลังเขียนอัลกอริธึมที่ต้องจัดการกับสำเนาของสถานะบอร์ดนับล้านนี่คือ microoptimization ก่อนวัยอันควรและไม่สามารถพิจารณาได้ ในสถานการณ์ปกติมันอาจจะไม่เร็วกว่าอยู่ดีเพราะการเข้าถึงบิตที่ไม่ได้จัดแนวนั้นต้องการการใช้งานบิตเสริม
Lie Ryan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.