作为一个库作者,期 望用户根据情况将null传递给方法参数是不是很糟糕? [关闭]

问题描述 投票:1回答:2

我正在尝试编写一个将由外部用户使用的库,我仍然坚持一些基本的设计决策。

我正在编写一个简单的POJO类,它将保存有关OAuth2令牌的一些信息。

本课程需要满足以下条件:

  • 如果令牌是永久令牌,则用户只需要传递令牌。
  • 如果令牌处于临时令牌中,则用户需要传递令牌,expirationDate和refreshToken。
  • 永远不会出现只有expirationDate和refreshToken中的一个为空的情况。两者都将为null或两者都将为非null。

这是我到目前为止:

public TokenInformation(String token, Date expirationDate, String refreshToken) {
    Objects.requireNonNull(token, "token parameter cannot be null.");
    this.token = token;

    if ((expirationDate != null) && (refreshToken != null)) {
        this.expiresIn = expiresIn;
        this.refreshToken = refreshToken;
        isPermanentToken = false;
    } else if ((expirationDate == null) && (refreshToken == null)) {
        this.expiresIn = null;
        this.refreshToken = null;
        isPermanentToken = true;
    } else {
        // throw some exception here
    }
}  

说实话,我对代码的外观并不完全满意。

但我确实有以下想法:

  • 有两个构造函数。一个只有一个参数(用于永久性令牌),另一个带有所有三个参数(临时令牌)。但是,我担心的是用户不会正确阅读文档,并会使用永久令牌构造函数来获取临时令牌。
  • 有两种不同的工厂方法而不是构造函数。这些工厂方法将被明确命名,因此用户使用错误方法的机会很小。此外,不会强制用户显式传入null。

我认为第二个想法可能是最好的方法。例如,我想不出任何要求我们传递null的Java API,这可能暗示我粘贴的代码是个坏主意。另外,Java使用了很多工厂方法,因此对于我的库用户来说,这不是一个陌生的模式。

我想要其他人的意见。如果您需要任何其他信息,请告诉我。

java api-design
2个回答
1
投票

我宁愿将永久和临时令牌行为封装到各自的域中,因此您的库的任何用户都清楚地知道实例化了哪种令牌

我认为建议的课程:

/**
 * The base class encapsulates the behavior of generic token
 */
public class AbstractToken {

    protected String token;

    // other properties that exist very closely with token

    public String getToken() {
        return token;
    }
}

永久令牌的域名

/**
 * The domain encapsulates the behaviour of Permanent token - token that never expires
 */
public class PermanentToken extends AbstractToken {

    // more attributes that makes general token as Parmament token

    /**
     * Instantiates a new Permanent token - this token never expires
     *
     * @param token the token
     */
    public PermanentToken(String token) {
        this.token = token;
    }
}

临时令牌的域名:

/**
 * The domain for Temporary token.
 */
public class TemporaryToken extends AbstractToken {

    private Date expirationDate;
    private String refreshToken;

    // more attributes that makes general token as temporary token

    /**
     * Instantiates a new Temporary token with token expiry date and refresh token
     *
     * @param token          the token
     * @param expirationDate the expiration date
     * @param refreshToken   the refresh token
     */
    public TemporaryToken(String token, Date expirationDate, String refreshToken) {
        this.token = token;
        this.expirationDate = expirationDate;
        this.refreshToken = refreshToken;
    }
}

现在,您图书馆的用户清楚地知道他/她想要实例化和使用的令牌类型。

附: - 我想您可以为您的域名保留更好的名称,并深入了解您的图书馆业务。


0
投票

基于上面的代码,我认为多重构造方法比工厂更合适。这是一个非常常见的Java设计模式,具有多个构造函数,用户可以在其中传递信息,只包含他们拥有数据的字段。构造函数不会重复代码,而是相互调用默认值。

public TokenInformation(String token) {
  this(token, null, null);
}

public TokenInformation(String token, Date expirationDate, String refreshToken) {
    Objects.requireNonNull(token, "token parameter cannot be null.");
    this.token = token;

    if ((expirationDate != null) && (refreshToken != null)) {
        this.expiresIn = expiresIn;
        this.refreshToken = refreshToken;
        isPermanentToken = false;
    } else if ((expirationDate == null) && (refreshToken == null)) {
        this.expiresIn = null;
        this.refreshToken = null;
        isPermanentToken = true;
    } else {
        // throw some exception here
    }
}

由于您没有创建多种不同类型的TokenInformation对象,因此我找不到符合您需求的工厂模式。如果你要使用一个模式,我会选择Builder而不是工厂。

编辑:我应该更好地阅读你的代码。我会在这里留下我的答案,因为我认为如果你不想改变你的课程我的解决方案仍然适用,但是,我认为@DHRUV BANSAL有更好的整体方法,因为你的代币实际上代表不同的东西

© www.soinside.com 2019 - 2024. All rights reserved.