Ich versuche, ein Servlet zu schreiben, das eine Aufgabe basierend auf dem Wert "action" ausführt, an den es als Eingabe übergeben wurde.
Hier ist das Beispiel davon
public class SampleClass extends HttpServlet {
public static void action1() throws Exception{
//Do some actions
}
public static void action2() throws Exception{
//Do some actions
}
//And goes on till action9
public void doPost(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {
String action = req.getParameter("action");
/**
* I find it difficult in the following ways
* 1. Too lengthy - was not comfortable to read
* 2. Makes me fear that action1 would run quicker as it was in the top
* and action9 would run with a bit delay - as it would cross check with all the above if & else if conditions
*/
if("action1".equals(action)) {
//do some 10 lines of action
} else if("action2".equals(action)) {
//do some action
} else if("action3".equals(action)) {
//do some action
} else if("action4".equals(action)) {
//do some action
} else if("action5".equals(action)) {
//do some action
} else if("action6".equals(action)) {
//do some action
} else if("action7".equals(action)) {
//do some action
} else if("action8".equals(action)) {
//do some action
} else if("action9".equals(action)) {
//do some action
}
/**
* So, the next approach i tried it with switch
* 1. Added each action as method and called those methods from the swith case statements
*/
switch(action) {
case "action1": action1();
break;
case "action2": action2();
break;
case "action3": action3();
break;
case "action4": action4();
break;
case "action5": action5();
break;
case "action6": action6();
break;
case "action7": action7();
break;
case "action8": action8();
break;
case "action9": action9();
break;
default:
break;
}
/**
* Still was not comfortable since i am doing un-necessary checks in one way or the other
* So tried with [reflection][1] by invoking the action methods
*/
Map<String, Method> methodMap = new HashMap<String, Method>();
methodMap.put("action1", SampleClass.class.getMethod("action1"));
methodMap.put("action2", SampleClass.class.getMethod("action2"));
methodMap.get(action).invoke(null);
/**
* But i am afraid of the following things while using reflection
* 1. One is Security (Could any variable or methods despite its access specifier) - is reflection advised to use here?
* 2. Reflection takes too much time than simple if else
*/
}
}
Alles, was ich brauche, ist, zu vielen if / else-if-Überprüfungen in meinem Code zu entkommen, um eine bessere Lesbarkeit und eine bessere Codepflege zu gewährleisten. Also versucht für andere Alternativen wie
1. Fall wechseln - es werden immer noch zu viele Überprüfungen durchgeführt, bevor meine Aktion ausgeführt wird
2. Reflexion
i] Eine Hauptsache ist die Sicherheit, mit der ich trotz des Zugriffsspezifizierers sogar auf die Variablen und Methoden innerhalb der Klasse zugreifen kann. Ich bin mir nicht sicher, ob ich sie in meinem Code verwenden kann
ii] und das andere ist, dass es mehr Zeit braucht als die einfachen if / else-if-Prüfungen
Gibt es einen besseren Ansatz oder ein besseres Design, das jemand vorschlagen könnte, um den obigen Code besser zu organisieren?
BEARBEITET
Ich habe die Antwort für das obige Snippet unter Berücksichtigung der folgenden Antwort hinzugefügt .
Die folgenden Klassen "ExecutorA" und "ExecutorB" führen jedoch nur wenige Codezeilen aus. Ist es eine gute Praxis, sie als Klasse hinzuzufügen, als sie als Methode hinzuzufügen? Bitte geben Sie diesbezüglich Hinweise.
quelle
Antworten:
Basierend auf der vorherigen Antwort ermöglicht Java, dass Aufzählungen Eigenschaften haben, sodass Sie ein Strategiemuster definieren können, wie z
Dann wäre deine
Executor
(Strategie)Und all dein Wenn / Sonst in deiner
doPost
Methode wird so etwas wieAuf diese Weise können Sie sogar Lambdas für die Testamentsvollstrecker in den Aufzählungen verwenden.
quelle
Executor
ist (oder kann) eine funktionale Schnittstelle.Verwenden Sie anstelle der Reflexion eine dedizierte Schnittstelle.
dh anstelle von:
Verwenden
Implementiert jede von ihnen für jede Aktion und dann:
Natürlich ist diese Lösung nicht die leichteste, daher müssen Sie möglicherweise nicht auf diese Länge gehen.
quelle
ProcessAction
stattActionProcess
ist das so ...?Verwenden Sie das Befehlsmuster . Dies erfordert eine Befehlsschnittstelle wie die folgende:
Wenn die
Actions
leicht und billig zu bauen sind, verwenden Sie eine Factory-Methode. Laden Sie die Klassennamen aus einer EigenschaftendateiactionName=className
, die die Aktionen für die Ausführung mit einer einfachen Factory-Methode erstellt und erstellt.Wenn die Erstellung der Aktionen teuer ist, verwenden Sie einen Pool, z. B. eine HashMap . In den meisten Fällen würde ich jedoch vorschlagen, dass dies nach dem Prinzip der Einzelverantwortung vermieden werden könnte, indem das teure Element an einen vorkonstruierten gemeinsamen Ressourcenpool delegiert wird und nicht an die Befehle selbst.
Diese können dann mit ausgeführt werden
Dies ist ein sehr robuster und entkoppelter Ansatz, der SRP, LSP und ISP der SOLID-Prinzipien anwendet . Neue Befehle ändern den Befehlszuordnungscode nicht. Die Befehle sind einfach zu implementieren. Sie können einfach zur Projekt- und Eigenschaftendatei hinzugefügt werden. Die Befehle sollten erneut eingegeben werden, was sie sehr performant macht.
quelle
Sie können das auf Aufzählung basierende Objekt verwenden, um die Notwendigkeit einer Hardcodierung der Zeichenfolgenwerte zu verringern. Dies spart Ihnen Zeit und macht den Code in Zukunft sehr ordentlich zu lesen und zu erweitern.
quelle
Das Muster der Factory-Methode ist das, wonach ich suche, wenn Sie nach skalierbarem und weniger wartbarem Design suchen.
Das Factory-Methodenmuster definiert eine Schnittstelle zum Erstellen eines Objekts. Lassen Sie jedoch die Unterklasse entscheiden, welche Klasse instanziiert werden soll. Mit der Factory-Methode kann eine Klasse die Instanziierung auf die Unterklasse verschieben.
action1, action2 ........ actionN konkrete Implementierung mit der doStuff-Methode, die die zu erledigenden Aufgaben implementiert.
Ruf einfach an
Wenn in Zukunft mehr Aktionen eingeführt werden, müssen Sie nur noch eine konkrete Klasse hinzufügen.
quelle
Mit Bezug auf @J. Pichardo Antwort Ich schreibe das Modifizieren des obigen Snippets wie folgt
quelle