Ich habe eine Klasse, die zur Verarbeitung von Kundenzahlungen verwendet wird. Mit einer Ausnahme sind alle Methoden dieser Klasse für jeden Kunden gleich, mit Ausnahme einer, die (zum Beispiel) berechnet, wie viel der Benutzer des Kunden schuldet. Dies kann von Kunde zu Kunde sehr unterschiedlich sein und es gibt keine einfache Möglichkeit, die Logik der Berechnungen in so etwas wie einer Eigenschaftendatei zu erfassen, da es eine beliebige Anzahl benutzerdefinierter Faktoren geben kann.
Ich könnte hässlichen Code schreiben, der basierend auf der Kunden-ID wechselt:
switch(customerID) {
case 101:
.. do calculations for customer 101
case 102:
.. do calculations for customer 102
case 103:
.. do calculations for customer 103
etc
}
Dies erfordert jedoch, dass die Klasse jedes Mal neu aufgebaut wird, wenn wir einen neuen Kunden erhalten. Was ist der bessere Weg?
[Bearbeiten] Der "doppelte" Artikel ist völlig anders. Ich frage nicht, wie ich eine switch-Anweisung vermeiden soll, sondern nach dem modernen Design, das für diesen Fall am besten geeignet ist - das ich mit einer switch-Anweisung lösen könnte, wenn ich Dinosaurier-Code schreiben möchte. Die dort bereitgestellten Beispiele sind allgemein gehalten und nicht hilfreich, da sie im Wesentlichen sagen: "Hey, der Schalter funktioniert in einigen Fällen ziemlich gut, in anderen nicht."
[Bearbeiten] Ich habe mich aus folgenden Gründen für die Antwort mit dem höchsten Rang entschieden (erstellen Sie eine separate "Kunden" -Klasse für jeden Kunden, der eine Standardschnittstelle implementiert):
Konsistenz: Ich kann eine Schnittstelle erstellen, die sicherstellt, dass alle Kundenklassen die gleiche Ausgabe erhalten und zurückgeben, auch wenn sie von einem anderen Entwickler erstellt wurden
Wartbarkeit: Der gesamte Code ist in der gleichen Sprache (Java) geschrieben, sodass niemand eine separate Programmiersprache erlernen muss, um das beizubehalten, was eine absolut einfache Funktion sein sollte.
Wiederverwendung: Falls im Code ein ähnliches Problem auftritt, kann ich die Customer-Klasse erneut verwenden, um eine beliebige Anzahl von Methoden zum Implementieren der "benutzerdefinierten" Logik zu speichern.
Vertrautheit: Ich weiß bereits, wie man das macht, damit ich es schnell erledigen und mich anderen, dringenderen Themen widmen kann.
Nachteile:
Für jeden neuen Kunden ist eine Kompilierung der neuen Kundenklasse erforderlich, wodurch die Kompilierung und Bereitstellung von Änderungen möglicherweise etwas komplexer wird.
Jeder neue Kunde muss von einem Entwickler hinzugefügt werden - ein Support-Mitarbeiter kann die Logik nicht einfach einer Eigenschaftendatei hinzufügen. Das ist nicht ideal ... aber dann war ich mir auch nicht sicher, wie ein Support-Mitarbeiter die erforderliche Geschäftslogik aufschreiben kann, insbesondere wenn sie (wie wahrscheinlich) mit vielen Ausnahmen komplex ist.
Es wird nicht gut skalieren, wenn wir viele, viele neue Kunden hinzufügen. Dies ist nicht zu erwarten, aber wenn es passiert, müssen wir viele andere Teile des Codes sowie diesen einen überdenken.
Für die von Ihnen Interessierten können Sie Java Reflection verwenden, um eine Klasse nach Namen aufzurufen:
Payment payment = getPaymentFromSomewhere();
try {
String nameOfCustomClass = propertiesFile.get("customClassName");
Class<?> cpp = Class.forName(nameOfCustomClass);
CustomPaymentProcess pp = (CustomPaymentProcess) cpp.newInstance();
payment = pp.processPayment(payment);
} catch (Exception e) {
//handle the various exceptions
}
doSomethingElseWithThePayment(payment);