ความแตกต่างระหว่างวิธีแม่แบบและรูปแบบกลยุทธ์คืออะไร?


161

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

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

อย่างไรก็ตามเท่าที่ลูกค้ามีความกังวลพวกเขาจะบริโภคในลักษณะเดียวกัน - ถูกต้องหรือไม่


2
โพสต์นี้ใน SO มีคำตอบที่ดีกว่าสำหรับคำถามเดียวกัน: stackoverflow.com/questions/464524/…
Gob00st

12
คำถามที่เชื่อมโยงกับ gob00st คือความแตกต่างระหว่างกลยุทธ์และสะพาน มันไม่ใช่คำตอบสำหรับคำถามนี้เลย
Bluekeys

คำตอบ:


135

ความแตกต่างที่สำคัญระหว่างสองคือเมื่อเลือกอัลกอริทึมที่เป็นรูปธรรม

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

class ConcreteAlgorithm : AbstractTemplate
{
    void DoAlgorithm(int datum) {...}
}

class AbstractTemplate
{
    void run(int datum) { DoAlgorithm(datum); }

    virtual void DoAlgorithm() = 0; // abstract
}

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

class ConcreteAlgorithm : IAlgorithm
{
    void DoAlgorithm(int datum) {...}
}

class Strategy
{
    Strategy(IAlgorithm algo) {...}

    void run(int datum) { this->algo.DoAlgorithm(datum); }
}

สรุป:

  • รูปแบบวิธีการเทมเพลต: การเลือกอัลกอริธึมเวลาคอมไพล์โดยคลาสย่อย
  • รูปแบบกลยุทธ์: การเลือกอัลกอริทึมรันไทม์ตามการบรรจุ

47
ทั้งสองรูปแบบสนับสนุนการเลือกรันไทม์ของอัลกอริทึมที่ใช้ (สำหรับวิธีเทมเพลตคุณจะทำอะไรเช่นif (config.useAlgoA) impl = new AlgoA() else impl = new AlgoB()นี้) ดังนั้นคำตอบนี้ไม่ถูกต้อง
Borek Bernard

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

21
-1 ฉันคิดว่าคำตอบนี้ (แม้ว่าจะไม่ผิดอย่างสมบูรณ์) พลาดจุดที่แตกต่างที่แท้จริง คำตอบ @ tvanfosson ดีกว่ามาก
Doc Brown

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

1
อัลกอริทึมที่เป็นรูปธรรมได้รับการคัดเลือกในลักษณะเดียวกันสำหรับทั้งสองรูปแบบ ทางเลือกที่จะทำโดยการกล่าวอ้างเมื่อเทียบกับnew ConcreteAlgorithm1() new ConcreteAlgorithm2()เห็นได้ชัดว่าตัวเลือกเกิดขึ้นที่รันไทม์ (การเลือกอัลกอริทึมในเวลารวบรวมจะหมายถึงฮาร์ดโค้ด) ความแตกต่างที่สำคัญระหว่างทั้งสองคือวิธีการใช้อัลกอริทึมที่เป็นรูปธรรม มันใช้งานเป็นคลาสย่อยหรือเป็นส่วนต่อประสานที่แยกจากกันหรือไม่? อดีตคือเทมเพลต หลังเป็นกลยุทธ์ ความแตกต่างสามารถสรุปได้ว่าเป็นองค์ประกอบเทียบกับการสืบทอดซึ่งเป็นรูปแบบทั่วไปของหนังสือ GoF
jaco0646

138

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

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

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


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

2
@BontToCode ฉันจะถือว่าสิ่งที่พวกเขากำลังพูดถึงคือการเลือกกลยุทธ์เฉพาะในเวลาทำงาน ตัวอย่างเช่นมีหลายวิธีในการหาตัวเลขของรากของสมการ ขึ้นอยู่กับโดเมนปัญหาหรือข้อมูลที่คุณอาจเลือก Newton-Raphson, Euler หรือกลยุทธ์อื่น ๆ ในการแก้สมการ หนึ่งในนั้นคือกลยุทธ์ อัลกอริทึมที่ใหญ่กว่าซึ่งการแก้สมการเป็นส่วนหนึ่งเลือกกลยุทธ์ที่จะจ้างงานโดยพิจารณาจากคุณภาพของปัญหา
tvanfosson

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

1
@BontToCode ฉันจะบอกว่ากลยุทธ์มีประโยชน์มากที่สุดเมื่อตัวเลือกเป็นแบบไดนามิก แม่แบบนั้นเป็นวิธีในการสร้างพฤติกรรมที่แตกต่างและเกี่ยวข้องกันเพื่อให้รู้จัก คุณจะใช้กลยุทธ์บางอย่าง (แม้ว่าจะไม่ใช่รูปแบบกลยุทธ์ที่จำเป็น) สำหรับการเลือกพฤติกรรมของเทมเพลตที่จะใช้ ตัวอย่างเช่นการสืบทอดผลิตภัณฑ์ - คุณต้องการสร้างผลิตภัณฑ์พื้นฐานเพิ่มคุณสมบัติสำหรับผลิตภัณฑ์ต่าง ๆ การเลือกประเภทผลิตภัณฑ์ (คลาส) เพื่อสร้างอินสแตนซ์อาจขึ้นอยู่กับว่าโหลดตาราง / มุมมองใด รูปแบบกลยุทธ์ไม่ได้เข้ามามีบทบาทจริงๆ
tvanfosson

2
@BontToCode มันไม่ใช่ / หรือสิ่งของมันคือใช่และ ใช้รูปแบบที่เหมาะสมรวมรูปแบบที่เป็นประโยชน์
tvanfosson

26

ฉันคิดว่าคลาสไดอะแกรมของทั้งสองลวดลายกำลังแสดงความแตกต่าง

กลยุทธ์
ห่อหุ้มอัลกอริทึมภายในคลาส
ลิงก์ไปยังรูปภาพ ป้อนคำอธิบายรูปภาพที่นี่

แม่แบบวิธี
เลื่อนขั้นตอนที่แน่นอนของอัลกอริทึมไปยังคลาสย่อย
ลิงก์ไปยังรูปภาพ ป้อนคำอธิบายรูปภาพที่นี่


24

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

ตัวอย่างของวิธีการแบบ:

Application.main()
{
Init();
Run();
Done();
}

ที่นี่คุณได้รับมรดกจากแอปพลิเคชันและแทนที่สิ่งที่จะทำใน init เรียกใช้และทำ

ตัวอย่างของกลยุทธ์:

array.sort (IComparer<T> comparer)

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


3
ฉันคิดว่านี่เป็นคำตอบที่ดี
Calanus

23

ความแตกต่างระหว่างกลยุทธ์และรูปแบบวิธีการกลยุทธ์แม่แบบและวิธีการแม่แบบ


ความคล้ายคลึงกัน

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


ความแตกต่าง

นี่คือความแตกต่างบางประการที่ฉันได้สังเกตขณะศึกษารูปแบบทั้งสองนี้:

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

ภาพที่นำมาจากบล็อกbitesized


19

การสืบทอดกับการรวม (เป็นกับการมี -a) เป็นสองวิธีในการบรรลุเป้าหมายเดียวกัน

คำถามนี้แสดงให้เห็นถึงการแลกเปลี่ยนระหว่างตัวเลือก: มรดกกับการรวม


11

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

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

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


9

แม่แบบวิธีการ:

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

โครงสร้างเทมเพลต _ :

ป้อนคำอธิบายรูปภาพที่นี่

กลยุทธ์:

  1. มันขึ้นอยู่กับการมอบหมาย / องค์ประกอบ
  2. มันเปลี่ยนความกล้าของวัตถุโดยการปรับเปลี่ยนพฤติกรรมวิธีการ
  3. มันใช้เพื่อสลับระหว่างตระกูลของอัลกอริทึม
  4. มันเปลี่ยนพฤติกรรมของวัตถุในเวลาทำงานโดยแทนที่หนึ่งอัลกอริทึมด้วยอัลกอริทึมอื่นในเวลาทำงาน
  5. การผูกจะทำในเวลาทำงาน

โครงสร้างกลยุทธ์ :

ป้อนคำอธิบายรูปภาพที่นี่

ดูที่วิธีการแม่แบบและบทความกลยุทธ์เพื่อความเข้าใจที่ดีขึ้น

กระทู้ที่เกี่ยวข้อง:

รูปแบบการออกแบบเทมเพลตใน JDK ไม่สามารถหาวิธีที่กำหนดชุดวิธีการที่จะดำเนินการตามลำดับ

ตัวอย่างโลกแห่งความจริงของรูปแบบกลยุทธ์


3

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

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

ดังนั้นบางครั้งลูกค้าจะบอกวัตถุที่ใช้กลยุทธ์ เช่นเดียวกับใน

myShippingCalculator.CalculateTaxes(myCaliforniaSalesTaxImpl);

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


3

ผมขอแนะนำให้คุณอ่านนี้บทความ มันอธิบายความแตกต่างในตัวอย่างกรณีจริง

ขอบคุณบทความจาก

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

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

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

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


2

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

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

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

จากhttp://cyruscrypt.blogspot.com/2005/07/template-vs-strategy-patterns.html


2

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

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


2

รูปแบบการออกแบบกลยุทธ์

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

รูปแบบการออกแบบวิธีการเทมเพลต

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

1

รูปแบบเทมเพลต:

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

public abstract class RobotTemplate {
    /* This method can be overridden by a subclass if required */
    public void start() {
        System.out.println("Starting....");
    }

    /* This method can be overridden by a subclass if required */
    public void getParts() {
        System.out.println("Getting parts....");
    }

    /* This method can be overridden by a subclass if required */
    public void assemble() {
        System.out.println("Assembling....");
    }

    /* This method can be overridden by a subclass if required */
    public void test() {
        System.out.println("Testing....");
    }

    /* This method can be overridden by a subclass if required */
    public void stop() {
        System.out.println("Stopping....");
    }

    /*
     * Template algorithm method made up of multiple steps, whose structure and
     * order of steps will not be changed by subclasses.
     */
    public final void go() {
        start();
        getParts();
        assemble();
        test();
        stop();
    }
}


/* Concrete subclass overrides template step methods as required for its use */
public class CookieRobot extends RobotTemplate {
    private String name;

    public CookieRobot(String n) {
        name = n;
    }

    @Override
    public void getParts() {
        System.out.println("Getting a flour and sugar....");
    }

    @Override
    public void assemble() {
        System.out.println("Baking a cookie....");
    }

    @Override
    public void test() {
        System.out.println("Crunching a cookie....");
    }

    public String getName() {
        return name;
    }
}

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

รูปแบบกลยุทธ์:

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

/**
 * This Strategy interface is implemented by all concrete objects representing an
 * algorithm(strategy), which lets us define a family of algorithms.
 */
public interface Logging {
    void write(String message);
}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class ConsoleLogging implements Logging {

    @Override
    public void write(String message) {
        System.out.println(message); 
    }

}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class FileLogging implements Logging {

    private final File toWrite;

    public FileLogging(final File toWrite) {
        this.toWrite = toWrite;
    }

    @Override
    public void write(String message) {
        try {
            final FileWriter fos = new FileWriter(toWrite);
            fos.write(message);
            fos.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }

}

สำหรับรหัสที่มาเต็มตรวจสอบ GitHub ของฉันที่เก็บ


0

กลยุทธ์ถูกเปิดเผยเป็นส่วนต่อประสานและวิธีเทมเพลตเป็น Abstract Class โดยทั่วไปจะใช้กรอบจำนวนมาก เช่นคลาส MessageSource ของ Spring Framework เป็นอินเตอร์เฟสกลยุทธ์สำหรับการแก้ไขข้อความ ลูกค้าใช้การใช้งานเฉพาะ (กลยุทธ์) ของอินเทอร์เฟซนี้

และการใช้งานนามธรรมของอินเตอร์เฟสเดียวกัน AbstractMessageSource ซึ่งมีการใช้งานร่วมกันของการแก้ไขข้อความและ exposes วิธีการแก้ปัญหา abstractCode () เพื่อให้คลาสย่อยสามารถใช้พวกเขาในรูปแบบของพวกเขา AbstractMessageSource เป็นตัวอย่างของวิธีการแบบ

http://docs.spring.io/spring/docs/4.1.7.RELEASE/javadoc-api/org/springframework/context/support/AbstractMessageSource.html


0

ในวิธีเทมเพลตของรูปแบบการออกแบบนี้ขั้นตอนวิธีหนึ่งขั้นหรือมากกว่านั้นสามารถถูกแทนที่โดยคลาสย่อยเพื่ออนุญาตให้มีพฤติกรรมที่แตกต่างกันในขณะที่มั่นใจว่าอัลกอริทึมการครอบคลุมนั้นยังคงติดตามอยู่ (Wiki)

รูปแบบชื่อแม่แบบวิธีการหมายความว่ามันคืออะไร สมมติว่าเรามีวิธี CalculateSomething () และเราต้องการเทมเพลตวิธีนี้ วิธีนี้จะถูกประกาศในชั้นฐานเป็นวิธีที่ไม่ใช่เสมือน พูดวิธีการที่ดูเหมือนนี้

CalculateSomething(){
    int i = 0;
    i = Step1(i);
    i++;
    if (i> 10) i = 5;
    i = Step2(i);
    return i;

} การใช้วิธีการ Step1 และ Step2 สามารถกำหนดโดยคลาสที่ได้รับ

ในรูปแบบกลยุทธ์ไม่มีการดำเนินการโดยฐาน (นี่คือเหตุผลว่าทำไมฐานเป็นอินเทอร์เฟซในแผนภาพคลาสจริง ๆ )

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

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

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