รูปแบบการออกแบบกลยุทธ์ที่ปรับเปลี่ยน


11

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

โดยพื้นฐานแล้วอัลกอริทึมของฉันบางส่วน (แต่ไม่ใช่ทั้งหมด) จำเป็นต้องมีพารามิเตอร์เพิ่มเติมหรือสองพารามิเตอร์ส่งผ่านไปยังพวกเขา

ดังนั้นฉันจะต้อง

  • ผ่านพวกเขาเป็นพารามิเตอร์พิเศษเมื่อฉันเรียกวิธีการคำนวณของพวกเขา

หรือ

  • เก็บไว้เป็นตัวแปรภายในคลาส ConcreteAlgorithm และสามารถอัพเดตได้ก่อนที่ฉันจะเรียกอัลกอริทึม

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

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

เพียงเพื่อความชัดเจนฉันกำลังใช้งานใน Java และดังนั้นจึงไม่มีความหรูหราของพารามิเตอร์ทางเลือก (ซึ่งจะแก้ปัญหานี้ได้อย่างดี)


พารามิเตอร์ทางเลือกเช่นใน C ++ จะไม่ช่วยอะไรเลยเนื่องจากเป็นเพียงชวเลขสำหรับการกำหนดวิธีโอเวอร์โหลดหลายวิธี
maaartinus

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

คำตอบ:


5

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

เช่น

StrategyParameter //Base strategy parameter that most of the strategies need
        ^
        |
        |
SpecialStrategyParameter // will be used for strategies that need more parameter

จากนั้นกำหนดลำดับชั้นกลยุทธ์เช่น:

Interface MyStrategy {
   void myStrategyMethod(StrategyParameter parameter);
}

class MyNormalStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

เรียกกลยุทธ์ข้างต้นเป็น: myNormalStrategyInstance.myStrategyMethod(strategyParameter);

class MySpecializedStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

เรียกกลยุทธ์ข้างต้นโดยผ่านSpecialStrategyParameterตัวอย่างแทนเช่น:mySpecializedStrategy.myStrategyMethod(specialStrategyParameter);

โปรดอัปเดตหากสิ่งที่ไม่ชัดเจน ยินดีที่จะอธิบาย / ชี้แจง


2
-1 ต้องใช้การลดทอนแบ่งการออกแบบห่อหุ้ม แม้ว่ามันจะเป็นการปรับปรุงการออกแบบในคำถาม แต่ก็มีวิธีที่ดีกว่าในการดูแลแมวตัวนี้
สูง

@tallseth ฉันเห็นว่าคนที่ใจร้อนเช่นกัน แต่ฉันไม่เห็นวิธีที่ดีกว่า คุณช่วยชี้ให้เห็นทางออกที่ดีกว่าได้ไหม? บทความหรืออะไร
Narek

จริง ๆ แล้วใช่ @ Jordãoมีคำตอบที่ฉันต้องการตามรายละเอียดที่เรามีในคำถาม คำตอบนั้นเล่นกับจุดแข็งของกลยุทธ์ ถ้าเราไปด้วยวิธีการในคำตอบนี้ฉันต้องการมีStrategyParameterparams ที่เป็นไปได้ทั้งหมดเช่นเดียวกับ DTO การปรับใช้กลยุทธ์บางอย่างอาจไม่สนใจสิ่งเหล่านี้ ในบางกรณีนั่นเป็นวิธีที่ดีที่สุด บริบทเป็นสิ่งสำคัญสำหรับปัญหาเหล่านี้
สูง

4

คุณจำเป็นต้องชี้แจงของคุณกลยุทธ์

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

ฉันเคยใช้กลยุทธ์ที่กำหนดค่าได้ก่อนหน้านี้ซึ่งคุณกำหนดพารามิเตอร์คลาสคอนกรีตในการก่อสร้าง:

interface Strategy {
  int calculate();
}

class ConcreteStrategyThatNeedsAParameter implements Strategy {
  private final int param;
  public ConcreteStrategyThatNeedsAParameter(int param) {
    this.param = param;
  }
  public int calculate() { 
    // uses param...
  }
}

ตอนนี้บางคนยังต้องการสร้างอินสแตนซ์ของคลาสนี้และส่งไปยังไคลเอนต์ของคุณ แต่ลูกค้าของคุณยังต้องรู้เกี่ยวกับStrategyอินเทอร์เฟซเท่านั้น

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


ไคลเอ็นต์คือสิ่งที่มีบริบทเพื่อจัดเตรียมพารามิเตอร์
andyczerwonka

1

ตราบใดที่มีการกำหนดลายเซ็นบนอินเทอร์เฟซอย่างชัดเจนก็ยังคงเป็นไปตามรูปแบบกลยุทธ์

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


0

ขยายคำตอบข้างต้นโดย peakit - คุณสามารถใช้นามธรรม ฉันกำลังใช้รหัสสูงสุดของที่นี่ -

อินเทอร์เฟซ MyStrategy { โมฆะนามธรรม myStrategyMethod (พารามิเตอร์ StrategyParameter); }

คลาส MyNormalStrategy ขยาย MyStrategy {public override void myStrategyMethod (พารามิเตอร์ StrategyParameter) {// ใช้ตรรกะที่นี่}}

คลาส MySpecializedStrategy ขยาย MyStrategy {public override void myStrategyMethod (พารามิเตอร์ StrategyParameter, ExtraStrategyParameter extraParameter) {// ใช้ตรรกะที่นี่} }

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


0

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

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