2

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

让我们使用一个身份验证示例。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
4

2 回答 2

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

一些处理程序策略:

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的 s 中封装错误处理和操作,这比 Visitor 的代码要少得多,因为您在这里并不需要双重调度。

于 2009-08-09T11:51:47.143 回答
1

我不建议将模式用于它们不是为意图而设计的。

访问者模式的意图是:

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

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

于 2009-08-09T11:17:05.683 回答