2009-08-09 3 views
2

Ich finde das nicht in Nutzungsszenarien für das Besuchermuster (oder vielleicht bekomme ich es nicht). Es ist auch nicht hierarchisch.Besucher Muster gegen Bedingungen?

Verwenden wir ein Authentifizierungsbeispiel. Ein UserAuthenticator authentifiziert die von einem Benutzer angegebenen Anmeldeinformationen. Es gibt ein Ergebnisobjekt zurück. Das Ergebnisobjekt enthält das Ergebnis der Authentifizierung: Authentifizierung erfolgreich, nicht erfolgreich, weil Benutzername nicht gefunden wurde, nicht erfolgreich, weil ungültige Zeichen verwendet wurden usw. Clientcode kann auf Bedingungen zurückgreifen, um dies zu behandeln. In Pseudo-Code:

AuthResult = Userauthenticator.authenticate(Username, Password) 
if AuthResult.isAuthenticated: do something 
else if AuthResult.AuthFailedBecauseUsernameNotFound: do something else 
else if etc... 

Würde ein Besuchermuster hier passen? :

Authresult.acceptVisitor(AuthVisitor) 

Authresult ruft dann eine Methode auf AuthVisitor auf das Ergebnis je:

AuthVisitor.handleNotAuthenticatedBecauseUsernameNotFound 

Antwort

1

Ich würde mit Muster für Vorsatz nicht empfehlen, sie für nicht gemacht wurden.

Die Absichten the visitor patterns sind:

  • eine Operation Stellen auf den Elementen einer Objektstruktur durchgeführt werden. Mit Visitor können Sie eine neue Operation definieren, ohne die Klassen der Elemente zu ändern, auf denen sie ausgeführt wird.
  • Die klassische Technik zur Wiederherstellung verlorener Informationen.
  • Tun Sie das Richtige, basierend auf dem Typ von zwei Objekten.
  • Doppel Versand

Diese Lösung wäre nützlich, wenn Sie verschiedene Authentifizierungsmethoden zu tun geplant hatte, aber wenn Sie ein auf nur tun wollen, werden Sie auf jeden Fall conditionals verwenden.

+0

Ich bin nicht damit einverstanden, nicht zu verwenden, wofür sie nicht gemacht wurden. Etwas kann ein Problem lösen, ohne dass es dazu gedacht ist. Wenn das Besuchermuster mein Problem auf eine gute Weise löst, warum sollte ich es dann nicht benutzen? Die Frage wird dann: ist die Lösung gut? Niemand, der es so benutzt, bedeutet nicht, dass es eine schlechte Lösung ist, obwohl es in diese Richtung deuten könnte. Wichtiger ist, warum es eine gute oder schlechte Lösung ist. Wenn McGyver Ihren Rat nahm, wäre er arbeitslos. – koen

+0

Eine andere Sache ist: Die Art, wie die Authentifizierung gehandhabt wird, ist für das Beispiel agnostisch. Ich sehe nicht, warum mein Beispiel UserAuthenticator auf nur eine Art der Authentifizierung beschränkt (zB nur LDAPUserAuthentication, OpenIdUserAuthentication usw.) – koen

1

Besucher ist ein wertvolles Design, wenn Ihre Daten nicht schnell ändern als Ihr Verhalten. Ein typisches Beispiel ist mit einem Parse-Baum:

  • Ihre Klassenhierarchie (Ihre Daten) eingefroren
  • Ihr Verhalten zu viel ändert, wollen Sie nicht Ihre Klassen das Hinzufügen einer anderen virtuellen Methode brechen

Ich glaube nicht, dass ein Besucher eine wertvolle Lösung hier ist, da jedes Mal, wenn Sie eine Unterklasse von AuthResult hinzufügen, Sie Ihren Besucher brechen.

Besucher ist etwa Handel Kapselung mit Doppel-Versand.

Sie können einen ähnlichen Ansatz versuchen:

interface Handler { 

    void onUsernameNotFound(); 

    void onWrongPassword(); 

    void authOk(); 
} 

interface Authenticator { 
    void authenticate(String username, String password, Handler handler); 
} 

class SimpleAuthenticator implements Authetnciator { 

    void authenticate(String username, String password, Handler handler) { 
     if (username.equals("dfa")) { 
      if (password.equals("I'm1337")) { 
       handler.authOk(); 
      } else { 
       handler.onWrongPassword(); 
      } 
     } else { 
      handler.onUsernameNotFound(); 
     } 
    } 
} 

einige Handler stategies:

class FatalHandler implements Handler { 

    void onUsernameNotFound() { 
     throw new AuthError("auth failed"); 
    } 

    void onWrongPassword() { 
     throw new AuthError("auth failed"); 
    } 

    void authOk() { 
     /* do something */ 
    } 
} 

und:

class DebugHandler implements Handler { 

    void onUsernameNotFound() { 
     System.out.println("wrong username"); 
    } 

    void onWrongPassword() { 
     System.out.println("wrong password"); 
    } 

    void authOk() { 
     System.out.println("ok"); 
    } 
} 

jetzt können Sie die Fehlerbehandlung und operatorion in Ihrem Handler s kapseln das ist viel weniger Code als Visitor, da du keine doppelte Dispa brauchst Tch hier.

+0

Ich würde dieses Design verwenden. Allerdings eine Beobachtung: Sie kommentieren, dass Besucher nicht geeignet ist, da jede neue Unterklasse von AuthResult Änderungen an dem Besucher erfordert. Hier entsprechen die Methoden auf Handler verschiedenen Ergebnissen, effektiv wäre es verschiedene Unterklassen von AuthResult gewesen. Dieselbe Kopplung betrifft ... neues mögliches Ergebnis Handler-Schnittstelle und alle Implementierungen ändern sich stark. Wenn wir zwei Dimensionen der Variabilität haben, Auth + Handler, wie weit sind wir eigentlich von Double Dispatch Requirement? – djna

+0

Ich muss etwas verpassen. Warum sollte eine Auth-Unterklasse für Besucher fehlschlagen? Es könnte eine abstrakte Basisklasse geben, die den acceptVisitor implementiert. Ich sehe, wie eine Strategie hier funktionieren würde, aber in einer Hinsicht ist eine Strategie mit Besucher IMHO verwandt, außer dass es keine Hierarchien macht. – koen

+0

@djna: mit Besucher du doppelte Logik, da Sie eine if-elseif-Kette benötigen, um die korrekte konkrete AuthResponse-Klasse zu erstellen ... dann brauchen Sie eine andere if-elseif-Kette zum Versenden – dfa

Verwandte Themen