Gibt es bekannte Entwurfsmuster für die Implementierung von Rabattmodellen?
Mit Rabattmodellen meine ich Folgendes:
Wenn ein Kunde Produkt X, Produkt Y und Produkt Z kauft, erhält er einen Rabatt von 10% oder 100 USD.
Wenn ein Kunde 100 Einheiten von Produkt X kauft, erhält er einen Rabatt von 15% oder 500 USD
Wenn ein Kunde im letzten Jahr mehr als 100.000 US-Dollar eingespielt hat, erhält er einen pauschalen Rabatt von 20%
Wenn ein Kunde 2 Einheiten von Produkt X gekauft hat, erhält er 1 Einheit von Produkt X (oder Produkt Y) gratis.
...
Gibt es ein generisches Muster, das für alle oben genannten Szenarien angewendet werden kann? Ich denke an einige Modelle, kann aber keine generische finden.
design
design-patterns
financial
Kanini
quelle
quelle
Antworten:
Wenn das Problem darin besteht, dass Sie unter bestimmten Umständen mehrere Rabatte anwenden müssen, sollten Sie das Muster der Verantwortungskette berücksichtigen .
Kurz gesagt, Sie geben die Informationen, die Sie verarbeiten möchten, an den ersten Prozessor weiter, und von dort entscheidet er, ob er sie an weitere Prozessoren weitergibt, bevor er das Ergebnis zurückgibt.
Auf diese Weise können Sie die Struktur und Reihenfolge der Prozessoren ändern, ohne den aufrufenden Code zu ändern.
quelle
Strategie-, Dekorations- und Statusmuster sind für mich die potenziellen Ausgangspunkte. Der Status kann für 2 oder 3 besonders nützlich sein, da 2 vom Status der Bestellung und 3 vom Status des Kunden innerhalb eines Zeitraums abhängt. Strategy and Decorator heben sich von den anderen ab, da Sie mithilfe der Strategie mehrere Algorithmen zur Berechnung des Auftragspreises implementieren und Decorator der Bestellung neue Rabatte hinzufügen können.
Denken Sie jedoch daran, dass Entwurfsmuster nur Modelle sind. Möglicherweise gilt nicht ein einziges Muster, sondern ein Mustersystem. Nehmen Sie auch Änderungen an den beschriebenen Modellen vor, damit sie besser zu Ihrer Lösung passen. Es ist besser, ein gutes Design zu haben, als ein Muster zu erzwingen, bei dem es nicht unbedingt hilft, nur um sagen zu können, dass Sie ein Muster haben.
quelle
Nun, ich würde ein Rabattmodell als Paar "Vorbedingung" und "Rabatt" entwerfen, wobei "Vorbedingung" eine Klasse mit Methoden ist
oder und
und Rabatt hat eine Methode
void ApplyTo(Customer c)
. Dies gibt Ihnen die Möglichkeit, jede Art von Vorbedingung mit jeder Art von Rabatt zu kombinieren (ich denke, dies ist eine Form von "Brückenmuster").Wenn Sie eine feste Anzahl von Voraussetzungen haben, können Sie das Problem lösen, indem Sie bestimmte Untertypen (Strategiemuster) erstellen. Wenn Ihre Vorbedingungen jedoch sehr komplex sein dürfen, können Sie mit logischen Anweisungen wie AND, OR und NOT eine Art Regelinterpreter für die Bedingungen implementieren. Die Regeln können eine einfache Textzeichenfolge sein, die in einer einfachen "domänenspezifischen Sprache" geschrieben ist.
Dasselbe gilt für die Klasse "Rabatt". Sie können entweder einige Untertypen für verschiedene Arten von Rabatten oder einen allgemeinen Ansatz verwenden, bei dem die Rabattregeln in Textform angegeben sind und von einem Interpreter ausgewertet werden.
quelle
Möglicherweise benötigen Sie eine IDiscount-Schnittstelle, da alle unterschiedlichen Rabatte gleich sind und wir sie konzeptionell als generische Rabatte behandeln möchten.
Die Klasse "Bestellung dieses Kunden" benötigt wahrscheinlich eine Sammlung von Rabatten. Liste? Hash? Verknüpfte Liste? Interessiert mich noch nicht. Rabatte gelten für den Kauf, nicht für den Kunden!
Halten Sie den Aufbau der Discount-Instanz von Kunden, Einkaufswagen, Verlauf usw. getrennt. Wie @jfrankcarr hervorhob, ändert sich viel.
Wahrscheinlich eine andere Klasse für jeden Rabatt, da der Algorithmus und die Parameter für jeden Rabatt stark und unvorhersehbar variieren.
Ich sehe eine Menge Event-Handling als Rabattberechnung, die auf Warenkorbänderungen reagiert und umgekehrt.
Design Pattern-Anwendung
strategy pattern
. IDiscount ist die Schnittstelle zur Implementierung verschiedener Rabattalgorithmen.Ich sehe ein
factory
. Sicherlich keine ausgewachseneabstract factory pattern
, sondern eine einzelne Klasse zu diesem Zeitpunkt in der Analyse. Es muss vernünftigerweise einen einzigen Ort geben, an dem ein ausreichender Zusammenhang besteht, um zu entscheiden, welche Rabatte gelten, und um sie dann zu erstellen. Eine Klasse. Wenn die Regeln für die spätere Anwendung von Rabatten aufgrund einer Pilzparty der Marketingabteilung explodieren, muss in dieser Basisfabrikklasse nach meinem Dafürhalten noch eine zusätzliche Rabattkonstruktionslogik zusammengeführt werden.Ich kann sehen
Chain of Responsibility
. Dies schließt sich nicht gegenseitig ausfactory
. Anstatt eine Rabattsammlung zu wiederholen, ruft jeder Rabatt den nächsten an. In der Klasse "Kundenbestellung" sind in diesem Fall keine Rabatte enthalten.Der Faktor "hmmmm ...." in der Kette der Verantwortung ist meiner Meinung nach, dass jeder Rabatt einen Verweis auf den nächsten hat. Die Implikation ist, dass Ordnung wichtig ist. Welches ist nicht der Fall. Das Konzept des AdR sieht außerdem vor, dass ein Objekt die Anfrage nicht bearbeiten kann, sodass sie "an die nächsthöhere Behörde" weitergeleitet wird. Unser Modell ist anders. Die einzige Bitte ist zu berechnen. Jeder Rabatt tut dies. Die Ausgabe oder der Effekt kann null sein, aber jeder Rabatt wird berechnet. Ich neige instinktiv zu einer höheren Treue in der realen Welt.
Annahmen
Was ändert sich, was bleibt gleich?
Rabatte sind sehr unterschiedlich. Unterschiedliche Anzahl und Art der Parameter für jede Regel.
Argumente für qualifizierende Rabatte ändern sich, wenn sich der Warenkorb ändert.
Die Anzahl der verfügbaren Rabatte ändert sich
Die Rabatte, die dieser Kunde bei Änderungen seines Einkaufswagens erhält, können geändert werden.
Die Einkaufsgeschichte ändert sich im Rahmen dieses Einkaufs nicht
Die Gesamtkosten ändern sich dynamisch in Abhängigkeit von den Kaufpositionen und den gewährten Rabatten.
Nach der erstmaligen Anwendung kann sich die Ausgabe eines Rabatts ändern, z. B. wenn sich die Kaufmenge ändert.
quelle
Ein Rabattmodell kann logischerweise alles sein , sodass Sie nicht davon ausgehen können, dass Sie alle Fälle im Voraus programmieren können. Auch kann niemand, der Ihre Frage beantwortet, völlig sicher sein, was Sie tatsächlich benötigen. Unter der Annahme, dass Sie die üblichen Rabatte erhalten, die in der realen Welt zu finden sind ...
Eine große Frage ist, ob die Rabatte programmiert werden oder ob Sie möchten, dass Benutzer sie eingeben. Wie oben erwähnt, kann man sie nicht niemals programmieren lassen, aber normalerweise besteht das Ziel darin, die Dateneingabe so zu gestalten, wie es für häufige Fälle der Fall ist, anstatt sie alle zu programmieren. Dies gilt zum Teil auch dann, wenn alle Rabatte von Programmierern erstellt werden.
Martin Fowler erwähnt "Einzelinstanzmethode" in "Analysemuster: wiederverwendbare Objektmodelle" als Teil der Implementierung von "Buchungsregeln" für Buchhaltungssysteme, aber die Regeln scheinen Ihren ziemlich ähnlich zu sein. Ich würde mehr Details geben, aber es ist ein urheberrechtlich geschütztes Werk und
Für eine Benutzeroberfläche müssen Sie entweder relativ einfache Anwendungsfälle entwickeln oder einen Interpreter und einen Abfrage-Builder erstellen. Möglicherweise beides, eines für einfache Fälle und eines für Fortgeschrittene. Wenn Sie einen Interpreter schreiben, ist dies wahrscheinlich ein recht guter Fall für die Verwendung des Interpreter-Musters, da der Code im Vergleich zu einem Parser-Generator relativ einfach ist und die langsamere Analysezeit wahrscheinlich keine Rolle spielt. (Wenn Sie Parser-Generatoren verwenden möchten, lassen Sie sich von mir nicht aufhalten.)
Versuchen Sie jedoch nicht, alles mit einem Dolmetscher zu erledigen - irgendwann programmieren Sie nur noch in Ihrer eigenen, miesen Sprache, also können Sie auch eine echte verwenden. Wenn Ihre interpretierte Sprache Funktionen unterstützt (wahrscheinlich sollte sie das Aufrufen unterstützen - es ist zweifelhaft, sie zu definieren), können diese in einer realen Sprache codiert werden. Gehen Sie nicht weiter, als Sie müssen.
Egal, was Sie tun, irgendwann möchte jemand, dass der Rabatt davon abhängt, ob er innerhalb von 30 Werktagen nach einer Werbeaktion gekauft hat - wobei Werktage nur dann zählen, wenn in der durch die Postleitzahl des Geschäfts oder die des Kunden definierten Region kein Feiertag war Postleitzahl. Versuchen Sie also nicht, das perfekte System im Voraus zu entwerfen - nehmen Sie an, dass Sie manchmal Code für neue Arten von Rabatten schreiben und entsprechend designen müssen.
quelle
Gibt es irgendeinen Grund zu fragen, ob es ein nützliches Muster dafür gibt? Welche Art von Muster ist erforderlich - strukturell oder verhaltensmäßig?
Wenn ich dafür eine Software schreibe, ist im Idealfall nur ein Algorithmus erforderlich . Eine einfache Funktion, die den Gesamtrabatt wie folgt berechnet:
Mehr brauchen Sie nicht!
Zur Verdeutlichung: Ich verstehe, dass es viele Regeln geben wird - die grundlegendste Form einer solchen Darstellung sollte die Form einer Regelbasis sein (Satz von Datenattributen und daraus resultierender Abschlag), und die Funktion wie oben würde sie iterieren, um sie zu berechnen. Wenn Regeln hinzugefügt oder entfernt werden, sollten Sie den Code nicht ändern - ändern Sie einfach die Regelbasis.
Muster werden nur benötigt, wenn wir unterschiedliche Objekte benötigen, um auf APIs voneinander zuzugreifen oder um zu kommunizieren, um eine Aufgabe einzurichten.
PS: Denken Sie darüber nach - wenn die Firewall Pakete verarbeitet und diese weiterleitet oder ablehnt (oder ändert) - welches Entwurfsmuster wird verwendet? Die Antwort ist KEINE der oben beschriebenen!
quelle