Design Pattern gesucht!

  • Themenstarter Themenstarter Gelöschtes Mitglied 5909
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 5909

Gast
Da ich einen kleinen Knoten im Kopf habe frage ich hier mal nach 🙂

Und zwar habe ich zwei recht ähnliche Objekte, die einen Status haben.
Ein persistentes Objekt und ein Transferobjekt.

Java:
class Persistent {
  String state;
  //...
}

enum state {
   NEW, EDIT, PRODUCTION
}

class Transfer {
  State state;
  //...
}

Das Transferobjekt kommt über einen REST Service rein,
das Persistent Objekt ist das ggf. vorhandene pendent in der DB.

Nun möchte ich vor und nach jedem Statuswechsel bestimmte aktionen auslösen.
Als erstes habe ich an das State Pattern gedacht, aber ich habe kein verhalten,
dass den Status verändert, sondern ich habe einen Status wechsel,
dass ein verhalten auslöst. Also genau umgekehrt.

Folgendes möchte ich erreichen:
Bevor das Transferobjekt gespeichert wird (und in ein Persistent Objekt gemapped wird),
will ich validierungen durchführen. Danach möchte ich z.B. eine Email verschicken.

Was ich nicht machen kann:
- Das Transferobjekt verändern (interfaces implementieren etc.)
- Die Transferobjekte sind generiert und werden immer neu generiert
- Im Persistent Objekt kann ich nicht das State enum verwenden

Was ich machen will:
- StateListener registrieren (aufruf vor und nach dem übergang)
- Den vorgang ggf. abbrechen (validierung fehlgeschlagen,...)
- das ganze erweiterbar halten (neue states und transitions)

Was ich vermeiden will:
Java:
if (oldstate == ... && newstate == ...)
else if (oldstate == ... && newstate == ...)
else if (oldstate == ... && newstate == ...)
else if (oldstate == ... && newstate == ...)
else if (oldstate == ... && newstate == ...)
else if (oldstate == ... && newstate == ...)

Was ich nicht nutzen will:
- BPM Engine oder vergleichbar, da zu komplex, kostet zu viel performance
(da ich primär für die Daten keine SQL DB verwende)

Irgendjemand eine brauchbare Idee?
 
Ich würde aus altem und neuem State einen Schlüssel basteln, und die zugehörige Aktion in einer Map ablegen, etwa:

Java:
Map<String, Runnable> map = new HashMap<String, Runnable>();
map.add("" + NEW + EDIT, new Runnable(){public void run(){ action1(); }});
map.add("" + NEW + PRODUCTION, new Runnable(){public void run(){ action2(); }});
...

Runnable r = map.get("" + oldstate + newstate);
if (r != null) r.run();

Statt Runnable könnte man natürlich auch einen spezialisierten funktionsartigen Wrapper benutzen, der z.B. passende Argumente akzeptiert.
 
Das sind schonmal sehr gute Denkanstöße, Danke!

Was haltet Ihr davon, wenn ich Landeis vorschlag mit dem Stragety Pattern kombiniere, sodass sich die angewandte Strategy aus dem zusammengesetzten Key Ergibt?

// Edit:

was haltet ihr davon? Da ich aber mehrere diese Objektpärchen habe muss ich mir nurnoch überlegen wie ich das möglichst generisch lösen kann, da ich die Transferobjekte keiner interfaces implementieren kann. Warscheinlich nehm ich da dann reflection.

Java:
class Transition {
	String oldState;
	State newState;
		
	// Transitions als Konstanten merken
	
	equals, hashcode!

}

interface TransitionContext {
	Persistent persistent;
	Transfer transfer;
}

interface TransitionListener {
	void beforeTransition(Transition, TransitionContext context);
	void afterTransition(Transition, TransitionContext context); 

}

class TransitionManager {

	Map<Transition, TransitionListener> listeners = new HashMap<Transition, TransitionListener>();

	void addTransitionListener(Transition transition, TransitionListener listener) {
		...
	}
	
	void beforeTransition(Persistent persistent, Transfer transfer) {
		TransitionContext context = createContext(persistent, transfer);
		Transition transition = getTransition(context);
		TransitionListener listener = listeners.get(transition);
		if (listener != null) {
			listener.beforeTransition(transition, context);
		}
	}

	void afterTransition(Persistent persistent, Transfer transfer) {
		TransitionContext context = createContext(persistent, transfer);
		Transition transition = getTransition(context);
		TransitionListener listener = listeners.get(transition);
		if (listener != null) {
			listener.afteTransition(transition, context);
		}
	}
	

}
 
Zuletzt bearbeitet von einem Moderator:

Neue Themen


Zurück
Oben