มีรูปแบบการออกแบบที่จะนำไปใช้กับแบบจำลองส่วนลดหรือไม่?


34

มีรูปแบบการออกแบบใดบ้างที่รู้จักกันในการใช้โมเดลจำลองส่วนลดหรือไม่?

ตามแบบจำลองส่วนลดฉันหมายถึงสิ่งต่อไปนี้:

  1. หากลูกค้าซื้อผลิตภัณฑ์ X, ผลิตภัณฑ์ Y และผลิตภัณฑ์ Z เขาจะได้รับส่วนลด 10% หรือ $ 100

  2. หากลูกค้าซื้อผลิตภัณฑ์ X 100 หน่วยเขาจะได้รับส่วนลด 15% หรือ $ 500

  3. หากลูกค้านำมาในปีที่แล้วมากกว่า $ 100K เขาจะได้รับส่วนลด 20%

  4. หากลูกค้าซื้อผลิตภัณฑ์ X 2 หน่วยเขาจะได้รับผลิตภัณฑ์ X (หรือ Y) 1 หน่วยฟรี

  5. ...

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


IIRC แบบฝึกหัดทั้งหมดที่ฉันเคยเห็นพร้อมตัวอย่างที่เกี่ยวข้องกับส่วนลด (มีจำนวนมาก) แนะนำรูปแบบกลยุทธ์
gnat

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

3
นอกจากนี้หากมีคนซื้อผลิตภัณฑ์ X 2 หน่วยหนึ่งผลิตภัณฑ์ Y และอีกหนึ่งผลิตภัณฑ์ Z จะได้รับทั้ง 10% และผลิตภัณฑ์ X พิเศษหรือไม่
Ubermensch

@ คาดว่าจะมีการเชื่อมโยงบางส่วนของบทเรียนเหล่านั้นได้โปรด
user16764

คำตอบ:


18

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

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

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


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

1
แค่ความเห็นของฉัน แต่ฉันคิดว่ามันน่าจะเป็น "ห่วงโซ่แห่งความรับผิดชอบ" มากกว่าการออกแบบสำหรับกรณีนี้ รายการแบบจำลองส่วนลดอย่างง่าย (ถ้าจำเป็นพร้อมด้วยหมายเลขการสั่งซื้อ) ควรทำ รายการนั้นเป็นอิสระจากลูกค้าและคำสั่งซื้อของเขาเนื่องจากลูกค้าทุกคนจะได้รับการปฏิบัติอย่างเท่าเทียมกัน "Chain of Responsibilty" เหมาะสมกว่าเมื่อรายการโมเดลส่วนลดเปลี่ยนบ่อยมาก ณ เวลาทำงานในลักษณะที่มีพลวัตสูง
Doc Brown

11

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

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


นั่นไม่ใช่สิ่งที่รูปแบบของรัฐตั้งใจจะทำใช่ไหม?
pdr

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

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

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

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

10

ฉันจะออกแบบโมเดลส่วนลดเป็นคู่ "Precondition" และ "Discount" โดยที่ "Precondition" เป็นคลาสที่มีวิธีการ

  bool IsFulfilled(Customer c);

หรือ / และ

  bool IsFulfilled(Customer c, Order o);

void ApplyTo(Customer c)และส่วนลดมีวิธีการ สิ่งนี้จะช่วยให้คุณสามารถรวมเงื่อนไขล่วงหน้าใด ๆ กับส่วนลดประเภทใดก็ได้ (ฉันคิดว่านี่เป็นรูปแบบของ "รูปแบบสะพาน")

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

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


สัญชาตญาณของฉันแสดงให้เห็นว่านี่อาจเป็นสิ่งที่เขากำลังมองหาในบริบทของคำถาม
Ubermensch

4
  • อาจต้องใช้ IDiscount ส่วนต่อประสานเนื่องจากส่วนลดที่ต่างกันทั้งหมดเป็นสิ่งเดียวกันและเราจะต้องการจัดการกับพวกเขาในเชิงแนวคิดในฐานะส่วนลดทั่วไป

  • คลาส "คำสั่งของลูกค้ารายนี้" อาจต้องมีชุดของส่วนลด รายการ? กัญชา? รายการที่เชื่อมโยง? ยังไม่สนใจ ส่วนลดใช้ได้กับการซื้อไม่ใช่ลูกค้า!

  • เก็บการสร้างอินสแตนซ์ส่วนลดแยกจากลูกค้าตะกร้าสินค้าประวัติ ฯลฯ มันจะเปลี่ยนไปมาก - ตามที่ @ jfrankcarr ชี้ให้เห็น

  • อาจเป็นคลาสที่แตกต่างกันสำหรับแต่ละส่วนลดเนื่องจากอัลกอริทึมและพารามิเตอร์สำหรับแต่ละส่วนลดแตกต่างกันอย่างมากและคาดเดาไม่ได้

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

การประยุกต์รูปแบบการออกแบบ

  • strategy patternฉันเห็น IDiscount เป็นอินเทอร์เฟซสำหรับการนำอัลกอริธึมส่วนลดต่างๆ
  • factoryฉันเห็น แน่นอนว่าไม่ใช่คนเต็มตัวabstract factory patternแต่เป็นชั้นเดียว ณ จุดนี้ในการวิเคราะห์ จะต้องมีสถานที่เดียวที่มีบริบทเพียงพอที่จะตัดสินใจว่าจะใช้ส่วนลดอย่างไรและจะสร้างได้อย่างไร ชั้นหนึ่ง หากกฎสำหรับการใช้ส่วนลดลดลงในภายหลังเนื่องจากฝ่ายเห็ดฝ่ายการตลาดตรรกะการก่อสร้างส่วนลดเพิ่มเติมใด ๆ ยังคงต้องรวมตัวกันในระดับโรงงานฐานนี้ฉันคิดว่า

  • Chain of Responsibilityฉันสามารถดู สิ่งนี้ไม่ได้เกิดจากfactoryแนวคิดร่วมกัน แทนที่จะทำซ้ำคอลเลกชันส่วนลดแต่ละส่วนลดจะเรียกผู้ชายคนต่อไป คลาส "คำสั่งซื้อของลูกค้า" ไม่มีการเก็บส่วนลดในกรณีนี้

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

สมมติฐาน

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

การเปลี่ยนแปลงอะไรสิ่งที่ยังคงเหมือนเดิม?

  • ส่วนลดแตกต่างกันมาก จำนวนและชนิดของพารามิเตอร์ที่แตกต่างกันในการสร้างแต่ละกฎ

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

  • จำนวนของการเปลี่ยนแปลงที่มีส่วนลด

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

  • ประวัติการช็อปปิ้งจะไม่เปลี่ยนแปลงในบริบทของการซื้อนี้

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

  • หลังจากแอปพลิเคชันเริ่มต้นผลลัพธ์ของส่วนลดอาจเปลี่ยนแปลงได้เช่นปริมาณการซื้อที่เปลี่ยนแปลง


คำตอบที่ยอดเยี่ยมและสมบูรณ์แบบ ... แต่ฉันมีเพียงความกังวลและเป็นส่วนของสมมติฐานที่ไม่ควรมีอย่างน้อยก็ไม่ต้องนำคำตอบ แนวคิดทั้งหมดคือรูปแบบที่ช่วยในการให้ความเชื่อมั่นและลืมเกี่ยวกับ "สมมติฐาน" กฎทั่วไปไม่จำเป็นต้องรู้วิธีการคำนวณจะทำและสิ่งที่ใช้รายละเอียดการใช้งานจากบริบท (ลูกค้ารายการรถเข็น , เวลากลางวันฤดูกาลเป็นต้น) ช่วยได้เต็มที่จริงๆ
le0diaz

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

1

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

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

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

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

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

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


0

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

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

cart.calculateDiscount(productVector);

คุณไม่ต้องการอะไรมากไปกว่านี้!

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

รูปแบบจะต้องเฉพาะในกรณีที่เราต้องการวัตถุที่แตกต่างกันจำเป็นต้องเข้าถึง API ของแต่ละอื่น ๆ หรือสื่อสารเพื่อนำงานในสถานที่

PS:คิดเกี่ยวกับมัน - เมื่อไฟร์วอลล์ประมวลผลแพ็กเก็ตและส่งหรือปฏิเสธแพ็กเก็ต (หรือแก้ไขมัน) - มันใช้รูปแบบการออกแบบอะไร? คำตอบคือไม่มีดังกล่าวข้างต้น!


แน่นอนคุณต้องการมากกว่านั้น !!! แนวคิดก็คือว่าอัลกอริทึมไม่ได้ควบคู่ไปกับการติดตั้งโค้ดอย่างแน่นหนา หากคุณตรวจสอบสถานการณ์ที่มีความเป็นไปได้สูงว่าสถานการณ์จะเกิดขึ้นมากขึ้นคุณก็พูดถึงมันอย่างใดเขาไม่ได้จริง ๆ ว่า 'กฎ' อื่นใดจะขึ้นอยู่กับ ไร้เดียงสาที่จะคิดว่ากฎจะขึ้นอยู่กับรายการผลิตภัณฑ์เท่านั้น แต่ในความเป็นจริงขึ้นอยู่กับลูกค้าเวลาฤดูกาลและอื่น ๆ Dont รู้ว่าสิ่งที่ดำเนินการตรวจสอบ Firewall คุณ แต่คนที่ผมได้ตรวจสอบจะมีรูปแบบการออกแบบโครงสร้าง / หลาย
le0diaz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.