รวมวิธีการแม่แบบกับกลยุทธ์


14

การมอบหมายในวิชาวิศวกรรมซอฟต์แวร์ของฉันคือการออกแบบแอพพลิเคชั่นที่สามารถเล่นเกมในรูปแบบที่แตกต่างกันได้ เกมดังกล่าวคือ Mancala เกมเหล่านี้บางเกมเรียกว่า Wari หรือ Kalah เกมเหล่านี้แตกต่างกันไปในบางแง่มุม แต่สำหรับคำถามของฉันเป็นสิ่งสำคัญที่ต้องรู้ว่าเกมดังกล่าวอาจแตกต่างกันดังต่อไปนี้:

  • วิธีการจัดการผลลัพธ์ของการย้าย
  • วิธีการกำหนดจุดสิ้นสุดของเกม
  • วิธีการตัดสินผู้ชนะ

สิ่งแรกที่ฉันนึกถึงในการออกแบบสิ่งนี้คือการใช้รูปแบบกลยุทธ์ฉันมีการเปลี่ยนแปลงในอัลกอริทึม (กฎที่แท้จริงของเกม) การออกแบบอาจมีลักษณะเช่นนี้: ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นฉันก็คิดกับตัวเองว่าในเกมของ Mancala และ Wari วิธีที่ผู้ชนะได้รับการตัดสินนั้นเหมือนกันและรหัสจะซ้ำกัน ฉันไม่คิดว่านี่เป็นคำจำกัดความที่ละเมิดหลักการ 'หนึ่งกฎที่เดียว' หรือหลักการของ DRY ที่เห็นว่าเป็นการเปลี่ยนแปลงในกฎสำหรับ Mancala ไม่ได้หมายความว่าจะต้องเปลี่ยนกฎใน Wari โดยอัตโนมัติเช่นกัน อย่างไรก็ตามจากข้อเสนอแนะที่ฉันได้รับจากอาจารย์ของฉันฉันได้รับความประทับใจในการค้นหาการออกแบบที่แตกต่าง

ฉันมากับสิ่งนี้: ป้อนคำอธิบายรูปภาพที่นี่

แต่ละเกม (Mancala, Wari, Kalah, ... ) จะมีคุณลักษณะของประเภทของส่วนต่อประสานของกฏแต่ละตัวเช่นWinnerDeterminerหากมีรุ่น Mancala 2.0 ซึ่งเหมือนกับ Mancala 1.0 ยกเว้นว่าผู้ชนะจะตัดสินได้อย่างไร ใช้รุ่น Mancala

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

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

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

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

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

ฉันยังไม่สามารถระบุได้ว่าใครจะรับผิดชอบในการสร้างTurnTemplateวัตถุในขณะที่ด้วยรูปแบบกลยุทธ์ฉันรู้สึกว่าฉันมีครอบครัวของวัตถุ (กฎสามข้อ) ซึ่งฉันสามารถสร้างได้ง่ายโดยใช้รูปแบบโรงงานนามธรรม จากนั้นฉันจะมี a MancalaRuleFactory, WariRuleFactoryฯลฯ และพวกเขาจะสร้างอินสแตนซ์ที่ถูกต้องของกฎและส่งกลับRuleSetวัตถุ

สมมติว่าฉันใช้กลยุทธ์ + รูปแบบนามธรรมจากโรงงานและฉันมีRuleSetวัตถุที่มีอัลกอริทึมสำหรับกฎสามข้อในนั้น วิธีเดียวที่ผมรู้สึกว่าผมยังสามารถใช้รูปแบบวิธีการแม่แบบนี้คือการส่งผ่านวัตถุของฉันRuleSet TurnTemplate'ปัญหา' ที่พื้นผิวนั้นคือฉันจะไม่ต้องการการใช้งานที่เป็นรูปธรรมของTurnTemplateชั้นเรียนเหล่านี้จะล้าสมัย ในวิธีการป้องกันของฉันในฉันเพิ่งจะเรียกTurnTemplate ruleSet.determineWinner()ผลที่ตามมาTurnTemplateชั้นเรียนจะไม่เป็นนามธรรมอีกต่อไป แต่จะต้องกลายเป็นรูปธรรมแล้วมันยังคงเป็นรูปแบบวิธีการของแม่แบบหรือไม่?

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


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

" ... ในเกมของ Mancala และ Wari วิธีที่ผู้ชนะจะได้รับการพิจารณานั้นเหมือนกันและรหัสจะซ้ำกัน " เหตุใดจึงแปลว่ารหัสซ้ำ ให้ทั้งสองคลาสเรียกใช้ฟังก์ชันเดียวกัน
D Drmmr

คำตอบ:


6

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

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

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

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

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


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

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

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

3

ความสับสนของคุณเป็นธรรม ประเด็นก็คือรูปแบบที่ไม่ได้เป็นเอกสิทธิ์เฉพาะบุคคลร่วมกัน

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

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

@ThomasOwens ให้คำแนะนำที่ดีเยี่ยมในการเข้าถึงปัญหาเฉพาะของคุณ


0

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


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

@YannisRizos และในขณะที่ฉันเห็นด้วยกับคุณเช่นกันฉันยังคงคิดว่าเขาให้คำแนะนำที่ดี (หรือข้อมูลเชิงลึกหากคำแนะนำไม่ใช่คำที่ถูกต้อง) ด้วยเหตุผลนั้น +1 แม้ว่าใช่มันไม่ใช่คำตอบที่เป็นประโยชน์มากในทางเทคนิค
ซื้อ 777

-1

ลองลงไปที่แทคทองเหลือง ไม่จำเป็นต้องมีส่วนต่อประสานเกมใด ๆ ไม่มีรูปแบบการออกแบบไม่มีคลาสนามธรรมและไม่มี UML

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

ดังนั้นวิธีที่สมเหตุสมผลในการไปที่นี่คือการใช้ฟังก์ชันนามธรรมที่เป็นนามธรรมเช่น C # Actionหรือ C ++ std::functionสร้าง Mancala หนึ่งอัน Wari หนึ่งและชั้น Kalah หนึ่งและไปจากที่นั่น

std::unordered_map<std::string, std::function<void()>> games = {
    { "Kalah", [] { return Kalah(); } },
    { "Mancala", [] { return Mancala(); } },
    { "Wari", [] { return Wari(); } }
};
void play() {
    std::function<void()> f;
    f = games[GetChoiceFromUI()];
    f();
    if (PlayAgain()) return play();
}
int main() {
    play();
}

เสร็จสิ้น

คุณไม่ได้เรียกเกม เกมโทรหาคุณ


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

3
ไม่มีอะไรจะพูดเกี่ยวกับพวกเขาเพราะไม่มีที่ไหนที่พวกเขาใช้ ไม่มีประเด็นที่คุณต้องใช้เวลาคิดว่าคุณจะออกแบบโดยใช้รูปแบบการออกแบบได้อย่างไรเว้นแต่คุณตั้งใจจะให้เป็นบทเรียนว่าจะไม่ใช้มันอย่างไร
DeadMG

4
มีแนวโน้มที่น่าเป็นห่วง / น่ารำคาญใน SoftDev ซึ่งรูปแบบการออกแบบที่ใช้นั้นมีความสำคัญมากกว่าแค่การแก้ปัญหา มีสิ่งหนึ่งที่เหมือนกับวิศวกรรมมากเกินไป
James

2
@DeadMG: ในขณะที่คุณทั้งคู่มีความถูกต้องในกรณีของ OP ปัญหาจะผ่านการสอบและการแก้ปัญหาคือการใช้รูปแบบการออกแบบและ UML ไม่ว่าเราจะถูกต้องแค่ไหนถ้าอาจารย์ของเขาไม่เห็นด้วยกับวิธีแก้ปัญหาของเขาเขาก็จะไม่ผ่าน
Goran Jovic

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