多态返回类型取决于结果的状态

时间:2016-03-25 16:37:50

标签: oop architecture return theory

我有以下方法:

attemptToGetToken(TokenRequestAttempt attempt);

我使用第三方组件来获取令牌但在某些情况下可能会失败(在尝试中无效或缺少参数)。

没有理由为这种情况抛出异常,因为它实际上预计会失败。

但是,根据结果,最终用户可能会采取相应行动。

这意味着我需要返回一个Object,允许用户决定它能做什么/应该做什么。

可能最明显的答案就是简单地拥有这样的课程:

class AttemptResult {

    constructor(status, token, errorMessage);
    getStatus();
    getToken();
    getErrorMessage();
    isSuccessful();
}

简单地返回正确填充的对象(我可以为成功/失败状态添加特定的工厂方法,但它只是一个工具)。

我对这种方法的问题是合同不明确。

如果失败,token将为null,但开发人员必须使用isSuccessful()方法检查尝试是否成功。 但没有什么可以阻止他拨打getToken()并获得null结果,这可能会在某处冒出错误。

所以我想知道实际归还两种物体是不是更好。

interface TokenAttemptResult {}

class FailedTokenAttempt implements TokenAttemptResult {

   getError();

}

class SuccessfulTokenAttempt implements TokenAttemptResult {

  getToken();
}

因为我实现了一个空接口来定义两个结果之间的关系,所以我现在可以在我的服务中使用这个接口作为返回类型:

TokenAttemptResult attemptToGetToken(TokenRequestAttempt attempt);

当用户调用上面的方法时,他负责检查返回类型并采取相应的行动,这会阻止他调用不应被调用的方法,并可能产生副作用。

您如何看待这种设计? 你们中的任何人都试过它并有任何反馈意见吗?

在没有实际论据的情况下,请避免涉及个人偏好的非建设性答案,我真的在寻找严谨的设计理论。

谢谢!

1 个答案:

答案 0 :(得分:1)

子类化方法将起作用,但是由于接口是开放的,客户端无法确定它们已经详尽地检查了接口的所有可能的实现类型。关闭可能案例的OO方法是visitor pattern例如

public interface TokenResultVisitor<TResult> {
    TResult Visit(FailedTokenAttempt failure);
    TResult Visit(SuccessfulTokenAttempt success);
}

然后

interface TokenAttemptResult {
    T Accept<T>(TokenResultVisitor visitor);
}

如果您只有两种可能的情况,这是一种相当重要的方法,因此如果您的语言支持一流函数,您可以简单地定义一个需要两个处理程序的方法,例如

interface TokenAttemptResult {
    T Handle<T>(success: Result => T, failure: TokenError => T);
}