针对条件的访问者模式?

发布于 2024-08-01 12:42:39 字数 641 浏览 6 评论 0原文

我似乎没有在访问者模式的使用场景中找到这一点(或者也许我不明白)。 它也没有等级之分。

让我们使用一个身份验证示例。 UserAuthenticator 验证用户提供的凭据。 它返回一个结果对象。 结果对象包含身份验证的结果:身份验证成功、由于未找到用户名而未成功、由于使用了非法字符而未成功等。客户端代码可以诉诸条件来处理此问题。 用伪代码来说:

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

I don't seem to find this in usage scenarios for the visitor pattern (or maybe I don't get it). It's also not hierarchical.

Let's use an authentication example. A UserAuthenticator authenticates credentials given by a user. It returns a result object. The result object contains the result of the authentication: authentication succeeded, not succeeded because username was not found, not succeeded because illegal characters were used etc. Client code may resort to conditionals to handle this.
In pseudocode:

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

Would a visitor pattern fit here? :

Authresult.acceptVisitor(AuthVisitor)

Authresult then calls a method on AuthVisitor depending on the result :

AuthVisitor.handleNotAuthenticatedBecauseUsernameNotFound

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷月断魂刀 2024-08-08 12:42:39

当您的数据不会随着您的行为而快速变化时,访问者是一个有价值的设计。 一个典型的例子是解析树:

  • 你的类层次结构(你的数据)被冻结
  • 你的行为变化太大,你不想破坏你的类添加另一个虚拟方法

我不认为访问者在这里是一个有价值的解决方案,因为每次添加 AuthResult 的子类都会破坏访问者。

Visitor是关于双重调度的交易封装

您可以尝试类似的方法:

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

一些处理程序策略:

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

现在您可以将错误处理和操作封装在您的处理程序中,这比访问者的代码少得多,因为您实际上不需要双重分派。

Visitor is a valuable design when your data doesn't change fast as your behaviour. A typical example is with a parse tree:

  • your class hierarchy (your data) is frozen
  • your behaviour varies too much, you don't want to break your classes adding another virtual method

I don't think that a Visitor is a valuable solution here, since each time you add a subclass of AuthResult you break your visitor.

Visitor is about trading encapsulation with double dispatch.

You can try a similar approach:

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

some Handler stategies:

class FatalHandler implements Handler {

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

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

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

and:

class DebugHandler implements Handler {

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

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

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

now you can encapsulate error handling and operatorion in your Handlers that is much less code than Visitor since you don't really need double dispatch here.

指尖凝香 2024-08-08 12:42:39

我不建议将模式用于非其目的的用途。

访问者模式的意图是:

  • 表示要对对象结构的元素执行的操作。 Visitor 允许您定义新操作,而无需更改其操作的元素的类。
  • 恢复丢失的类型信息的经典技术。
  • 根据两个对象的类型做正确的事情。
  • 双重调度

如果您计划执行各种身份验证方法,则此解决方案将很有用,但如果您计划只执行一种方法,则无论如何都必须使用条件。

I would not recommend using patterns for intent they were not made for.

The intents of the visitor patterns are:

  • Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
  • The classic technique for recovering lost type information.
  • Do the right thing based on the type of two objects.
  • Double dispatch

This solution would be useful if you had planned to do various authentification methods, but if you plan on only doing one, you'll have to use conditionals anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文