2009-08-09 75 views
2

我似乎沒有在訪問者模式的使用場景中找到它(或者我可能沒有得到它)​​。它也不是分層的。針對條件的訪問者模式?

讓我們使用身份驗證的例子。 UserAuthenticator認證用戶給出的憑證。它返回一個結果對象。結果對象包含身份驗證結果:身份驗證成功,未成功,因爲未找到用戶名,未成功,因爲使用了非法字符等。客戶端代碼可能會使用條件來處理此問題。 In pseudocode:

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

訪客模式會適合在這裏嗎? :

Authresult.acceptVisitor(AuthVisitor) 

Authresult然後調用AuthVisitor的方法根據結果:

AuthVisitor.handleNotAuthenticatedBecauseUsernameNotFound 

回答

1

我不會建議使用模式,因爲還沒有爲取得意圖。

the visitor patterns的意圖是:

  • 表示待上的對象結構的元件所執行的操作。訪問者可以讓你定義一個新的操作而不需要改變它所操作的元素的類。
  • 經典技術來恢復丟失的類型信息。
  • 做基於兩個對象的類型是正確的。
  • 雙重分派

如果你計劃做各種認證方法,該解決方案將是有益的,但如果你打算只做一個,你無論如何都要使用條件。

+0

我不同意不使用他們沒有製造的東西。有些東西可能會解決問題而不打算這樣做。如果訪問者模式能夠很好地解決我的問題,爲什麼我不應該使用它?那麼問題就變成:解決方案是否是一個好的解決方案。沒有人以這種方式使用這並不意味着它是一個不好的解決方案,儘管它可能暗示了這個方向。更重要的是爲什麼這是一個好的或壞的解決方案。 如果McGyver接受了你的建議,他將會失業。 – koen 2009-08-09 11:56:29

+0

另一件事是:認證處理的方式是不可知的例子。我不明白爲什麼我的示例將UserAuthenticator限制爲只有一種身份驗證方式(例如,只有LDAPUserAuthentication,OpenIdUserAuthentication等) – koen 2009-08-09 11:58:22

1

遊客是當你數據不爲自己的行爲快速更改寶貴的設計。一個典型的例子是一個解析樹:

  • 你的類層次結構(數據)被凍結
  • 您的行爲而改變太多,你不想打破你的類增加一個虛方法

我不認爲一個遊客在這裏是有價值的解決方案,因爲每次你添加AuthResult的子類,你打破你的訪問者。

遊客大約是交易封裝雙調度

您可以嘗試類似的做法:

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(); 
     } 
    } 
} 

一些處理程序策略及DCS:

class FatalHandler implements Handler { 

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

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

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

和:

class DebugHandler implements Handler { 

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

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

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

現在你可以封裝在Handler■錯誤處理和operatorion這比Visitor少得多的代碼,因爲你並不需要雙重dispa這裏。

+0

我會使用此設計。然而,有一種觀察:您評論說訪問者不適合,因爲AuthResult的每個新子類都需要對訪問者進行更改。這裏Handler上的方法對應於不同的結果,有效地是AuthResult的不同子類。同樣的耦合屬於...新的可能結果Handler接口和所有實現都有很大變化。鑑於我們有兩個維度的變化,Auth + Handler,我們實際上距離Double Dispatch需求有多遠? – djna 2009-08-09 12:00:17

+0

我必須錯過一些東西。爲什麼Auth子類會對訪問者失敗?可能有一個實現acceptVisitor的抽象基類。 我看到一個策略如何在這裏工作,但在某種程度上,一個策略與訪客恕我直言相關,除了它不做層次結構。 – koen 2009-08-09 12:04:29

+0

@djna:由於您需要一個if-elseif鏈來構建正確的具體AuthResponse類,因此您需要重複訪問邏輯......然後您需要另一個if-elseif鏈來進行調度 – dfa 2009-08-09 13:12:38